diff --git a/modcc/parser.cpp b/modcc/parser.cpp index 55960aa3cd9a3fe547499f9d1c48c92286ccf109..753b0b80c3892c71f810f48e73176d1773ebee25 100644 --- a/modcc/parser.cpp +++ b/modcc/parser.cpp @@ -399,9 +399,16 @@ void Parser::parse_state_block() { } parm.token = token_; - //state_block.state_variables.push_back(token_.spelling); get_token(); + if(token_.type == tok::from) { + // silently skips from/to + from_to_description(); + if (status_ == lexerStatus::error) { + return; + } + } + // get unit parameters if (line == location_.line && token_.type == tok::lparen) { parm.units = unit_description(); @@ -763,6 +770,10 @@ std::pair<Token, Token> Parser::range_description() { } get_token(); + if(token_.type != tok::integer) { + error(pprintf("range description must be <int, int>, found '%'", token_)); + return {}; + } lb = token_; get_token(); @@ -772,6 +783,10 @@ std::pair<Token, Token> Parser::range_description() { } get_token(); + if(token_.type != tok::integer) { + error(pprintf("range description must be <int, int>, found '%'", token_)); + return {}; + } ub = token_; get_token(); @@ -784,6 +799,39 @@ std::pair<Token, Token> Parser::range_description() { return {lb, ub}; } +std::pair<Token, Token> Parser::from_to_description() { + Token lb, ub; + + if(token_.type != tok::from) { + error(pprintf("range description must be of form FROM <int> TO <int>, found '%'", token_)); + return {}; + } + + get_token(); + if(token_.type != tok::integer) { + error(pprintf("range description must be of form FROM <int> TO <int>, found '%'", token_)); + return {}; + } + lb = token_; + + get_token(); + if(token_.type != tok::to) { + error(pprintf("range description must be of form FROM <int> TO <int>, found '%'", token_)); + return {}; + } + + get_token(); + if(token_.type != tok::integer) { + error(pprintf("range description must be of form FROM <int> TO <int>, found '%'", token_)); + return {}; + } + ub = token_; + + get_token(); + return {lb, ub}; +} + + // Returns a prototype expression for a function or procedure call // Takes an optional argument that allows the user to specify the // name of the prototype, which is used for prototypes where the name @@ -804,7 +852,6 @@ expression_ptr Parser::parse_prototype(std::string name=std::string()) { // check for an argument list enclosed in parenthesis (...) // return a prototype with an empty argument list if not found if( token_.type != tok::lparen ) { - //return make_expression<PrototypeExpression>(identifier.location, identifier.spelling, {}); return expression_ptr{new PrototypeExpression(identifier.location, identifier.spelling, {})}; } @@ -822,6 +869,14 @@ expression_ptr Parser::parse_prototype(std::string name=std::string()) { get_token(); // consume the identifier + // args may have a unit attached + if(token_.type == tok::lparen) { + unit_description(); + if(status_ == lexerStatus::error) { + return {}; + } + } + // look for a comma if(!(token_.type == tok::comma || token_.type==tok::rparen)) { error( "expected a comma or closing parenthesis, found '" diff --git a/modcc/parser.hpp b/modcc/parser.hpp index 49512f7ef5053926438494f9544afacca09f8237..a250ee8c5b6a6b866e65604b176d175cae993dd6 100644 --- a/modcc/parser.hpp +++ b/modcc/parser.hpp @@ -69,6 +69,7 @@ private: std::string value_literal(); int value_signed_integer(); std::pair<Token, Token> range_description(); + std::pair<Token, Token> from_to_description(); /// build the identifier list void add_variables_to_symbols(); diff --git a/modcc/token.cpp b/modcc/token.cpp index 8348a6e8a219ba3c9b5f16850cfdfb81b7586610..30ed8def41408a16c6f37022d4d1a7b021a0cd75 100644 --- a/modcc/token.cpp +++ b/modcc/token.cpp @@ -54,6 +54,8 @@ static Keyword keywords[] = { {"COMPARTMENT", tok::compartment}, {"METHOD", tok::method}, {"STEADYSTATE", tok::steadystate}, + {"FROM", tok::from}, + {"TO", tok::to}, {"if", tok::if_stmt}, {"IF", tok::if_stmt}, {"else", tok::else_stmt}, diff --git a/modcc/token.hpp b/modcc/token.hpp index 3c5344a49b461c1c8d2fb827e83f924ac7dd99e1..21648dcdb84a0094be95eeb02c0b18b1e5c927ce 100644 --- a/modcc/token.hpp +++ b/modcc/token.hpp @@ -64,6 +64,7 @@ enum class tok { solve, method, steadystate, threadsafe, global, point_process, + from, to, // prefix binary operators min, max, diff --git a/test/unit-modcc/test_parser.cpp b/test/unit-modcc/test_parser.cpp index 11e6e51b8a90eae3c306dd3460194837718e80ac..10952756306fb90b3866f55cd9f4e89399c2ccfa 100644 --- a/test/unit-modcc/test_parser.cpp +++ b/test/unit-modcc/test_parser.cpp @@ -93,7 +93,7 @@ TEST(Parser, procedure) { " y = a + b *c + a + b\n" "}" , - "PROCEDURE trates(v) {\n" + "PROCEDURE trates(v (mV)) {\n" " LOCAL qt\n" " qt=q10^((celsius-22)/10)\n" " minf=1-1/(1+exp((v-vhalfm)/km))\n" @@ -685,6 +685,10 @@ TEST(Parser, parse_state_block) { "STATE {\n" " h (nA)\n" " m (nA) r (uA)\n" + "}", + "STATE {\n" + " h FROM 0 TO 1\n" + " m r (uA)\n" "}" };