From fbd0479ff17317c6adb7ea405d11b7734b738eb3 Mon Sep 17 00:00:00 2001 From: "Mike D. Lowis" Date: Thu, 3 May 2012 15:13:43 -0400 Subject: [PATCH] Overhauled parser and lexer for symbolic based syntax --- example.dl | 251 +---- source/dllexer/dllexer.cpp | 195 +--- source/dllexer/dllexer.h | 68 +- source/dlparser/dlparser.cpp | 589 ++-------- source/dlparser/dlparser.h | 89 +- source/main.cpp | 15 +- source/visitors/scheme/scheme.cpp | 160 +-- tests/test_dllexer.cpp | 217 +--- tests/test_dlparser.cpp | 1756 ++++++++++++++--------------- 9 files changed, 1155 insertions(+), 2185 deletions(-) diff --git a/example.dl b/example.dl index fcacd8a..6890240 100644 --- a/example.dl +++ b/example.dl @@ -1,195 +1,58 @@ -#------------------------------------------------------------------------------ -# Literal Definition and Usage -#------------------------------------------------------------------------------ - -# Nums -foo := 1 -foo = -1 -foo = 1.0 -foo = -1.0 -foo = 10.0e1 -foo = 10.0e-1 -foo = -10.0e1 -foo = -10.0e-1 - -# Char -foo = 'a' -foo = '\a' -foo = '\b' -foo = '\n' -foo = '\r' -foo = '\t' -foo = '\v' - -# String -foo = "some string" -foo = "foo \a \b \f \n \r \t \v \' \" \\ \xFF bar" -foo = "12345"[2] - -# Symbol -foo = $some_symbol - -# Map -foo = @{} -foo.stuff = "bar" -foo = @{ - $foo : 1 + 1, - "stuff" : 2 + 2, - $stuff : 2 + 2, - $bar : 3 + 3, -} - -# Setting map elements -foo["stuff"] = 3 -foo.stuff = 5 - -# Vector -foo = [] -foo = [1] -foo = [1,2,3] -foo = foo[1] -foo = [1,2,3,4,5][2] - -# Setting Vector Elements -foo[2] = 6 - -# List -foo = () -foo = (1,) -foo = (1,2,3) -foo = foo[1] -foo = (1,2,3,4,5)[2] - -# Setting List Elements -foo[2] = 6 - -# Block -foo = { 1 + 1 } -foo = {|a| a + 1} -foo = {|a,b| a + b } -foo = foo(1,2) -foo = ({|a,b| a + b })(1,2) - -#------------------------------------------------------------------------------ -# Operators and Precedence Tests -#------------------------------------------------------------------------------ - - -#------------------------------------------------------------------------------ -# Macro Definition and Usage -#------------------------------------------------------------------------------ -assert := {|cond,msg| - exec_if(cond,{},{ print(msg) }) -} - -# Define a macro that represents a traditional if statement -% if [ - (E B B) : exec_if($1, $2, $3), - (E B) : exec_if($1, $2), -] - -test_result = false -if (1 < 2) -{ - test_result = true -}{ - test_result = false -} -assert( test_result, "First branch should be taken when test condition is true" ) - -test_result = false -if (1 > 2) -{ - test_result = false -}{ - test_result = true -} -assert( test_result, "Second branch should be taken when test condition is false" ) - -test_result = false -if (1 < 2) -{ - test_result = true -} -assert( test_result, "Branch should be taken when test condition is true" ) - -test_result = true -if (1 > 2) -{ - test_result = false -} -assert( test_result, "Branch should not be taken when test condition is false" ) - -#------------------------------------------------------------------------------ -# Delayed Evaluation -#------------------------------------------------------------------------------ - -############################################################################### -# WARNING: This Section is a work in progress. Please ignore it for now. # -############################################################################### - -# Define a function that makes a promise -#make_promise := {|expr| -# result := expr -# { -# print( "expr: ", expr ) -# print( "result: ", result ) -# result -# #if result_ready == true { -# # print("Returning cached results") -# # result -# #}{ -# # print("Caching results") -# # result -# #} -# } -#} - -# Define a macro that will delay the evaluation of the following expression -#% delay [ -# (E) : make_promise({ $1 }) -#] - -# Define a macro that will force the evaluation of the following delayed statement -#% force [ -# (E) : $1() -#] +# Literals +"foo" +'a' +1.0 +$foo + +# Function Application +foo() +foo(1) +foo(1 2) +foo(1 2 3) + +# Definition and assignment +define(foo 5) +set(foo 6) + +# Lambda expressions +lambda(()) +lambda((a)) +lambda((a b)) +lambda((a b c)) + +lambda(() + foo()) +lambda((a) + foo(a)) +lambda((a b) + foo(a b)) +lambda((a b c) + foo(a b c)) + +# Begin block +begin() +begin( foo() ) +begin( + foo() + bar()) + +# If statement +if( conditional + if_branch + else_branch ) + +if( conditional + if_branch ) + +# Infix operator expression +(1 add 1) +((1 add 1) add 1) +(1 add (1 add 1)) + +# Macros +#macro( +# [(_ a ':=' b) +# define(a b)] +# [(_ a '=' b) +# set(a b)]) # -#foo = delay 1 + 1 -#print("foo: ", foo) -#foo = force foo -#print("foo: ", foo) -#print( force foo ) -#print( force foo ) -#print( force foo ) - -#------------------------------------------------------------------------------ -# Classes -#------------------------------------------------------------------------------ - -# Define a macro for creating new classes -% class [ - (B) : { - this := @{} - $1() - this - }, -] - -# Simple class definition (No inheritance supported) -Animal := class { - # The sound of the mating call is kept private - priv_call := "Moo!" - - # Define a method to print the mating call sound - this.mating_call = { - print( priv_call ) - } -} - -# Animal is a constructor so call it to create a new cow -Cow := Animal() - -# And call the method to print the sound (This syntax needs to be cleaned up a bit) -(Cow.mating_call)() - diff --git a/source/dllexer/dllexer.cpp b/source/dllexer/dllexer.cpp index ebf4896..a3fd9e7 100644 --- a/source/dllexer/dllexer.cpp +++ b/source/dllexer/dllexer.cpp @@ -4,22 +4,6 @@ using namespace std; -#define NUM_SINGLE_CHAR_MATCHES 12 -SingleCharMatch_T Single_Character_Matches[ NUM_SINGLE_CHAR_MATCHES ] = { - { '[', LBRACK }, - { ']', RBRACK }, - { '(', LPAR }, - { ')', RPAR }, - { '{', LBRACE }, - { '}', RBRACE }, - { ',', COMMA }, - { '+', ADD }, - { '*', MUL }, - { '/', DIV }, - { '.', MEMB }, - { '%', MACRO }, -}; - DLLexer::DLLexer(std::istream& in) : LLNLexer(in) { } @@ -43,18 +27,6 @@ bool DLLexer::isDigit(void) return ((lookahead(1) >= '0') && (lookahead(1) <= '9')); } -bool DLLexer::isOperator(void) -{ - return ( (lookahead(1) == '=') - || (lookahead(1) == '!') - || (lookahead(1) == '<') - || (lookahead(1) == '>') - || (lookahead(1) == '|') - || (lookahead(1) == '&') - || (lookahead(1) == ':') - || (lookahead(1) == '@')); -} - bool DLLexer::isStringChar(void) { return ( (lookahead(1) != '"') @@ -70,7 +42,7 @@ Token DLLexer::next(void) // the EOF and skipping the loop (void)lookahead(1); - // If we have non-EOF chars tehn process them + // If we have non-EOF chars then process them while ( !eof() && (ret.type() == EOF) ) { if (isWhiteSpace()) @@ -81,18 +53,22 @@ Token DLLexer::next(void) { COMMENT(); } - else if (isLetter()) - { - Id(ret); - } - else if( isOperator() ) - { - MultiCharOp(ret); - } else if (isDigit()) { Number(ret,false); } + else if(lookahead(1) == '-') + { + consume(); + if(isDigit()) + { + Number(ret,true); + } + else + { + throw Exception(line,column); + } + } else if(lookahead(1) == '\'') { Char(ret); @@ -105,21 +81,21 @@ Token DLLexer::next(void) { Symbol(ret); } - else if(lookahead(1) == '-') + //* + else if (lookahead(1) == '(') { consume(); - if(isDigit()) - { - Number(ret,true); - } - else - { - ret = Token(SUB, line, column - 1); - } + ret = Token( LPAR, "(", line, column ); } + else if (lookahead(1) == ')') + { + consume(); + ret = Token( RPAR, ")", line, column ); + } + // */ else { - SingleCharOp(ret); + Id(ret); } } @@ -295,131 +271,6 @@ void DLLexer::Symbol(Token& tok) tok = Token( SYMBOL, oss.str(), line, column ); } -void DLLexer::SingleCharOp(Token& tok) -{ - for(int i = 0; i < NUM_SINGLE_CHAR_MATCHES; i++) - { - if(lookahead(1) == Single_Character_Matches[i].match) - { - consume(); - tok = Token( Single_Character_Matches[i].type, line, column ); - break; - } - } - - if( tok.type() == EOF) - { - Exception ex(line,column); - ex << "Unrecognized token"; - throw ex; - } -} - -void DLLexer::MultiCharOp(Token& tok) -{ - // save the current token so we can refer back to it - char last = lookahead(1); - // remove the current token from the buffer so we cna see the next - consume(); - - if(last == '=') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(EQ, line, column); - } - else - { - tok = Token(ASSIGN, line, column); - } - } - else if(last == '!') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(NE, line, column); - } - else - { - tok = Token(NOT, line, column); - } - } - else if(last == '<') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(LTE, line, column); - } - else - { - tok = Token(LT, line, column); - } - } - else if(last == '>') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(GTE, line, column); - } - else - { - tok = Token(GT, line, column); - } - } - else if(last == '|') - { - if(lookahead(1) == '|') - { - consume(); - tok = Token(OR, line, column); - } - else - { - tok = Token(PIPE, line, column); - } - } - else if((last == '&') && (lookahead(1) == '&')) - { - consume(); - tok = Token(AND, line, column); - } - else if(last == ':') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(DEFN, line, column); - } - else - { - tok = Token(SEP, line, column); - } - } - else if(last == '@') - { - if(lookahead(1) == '=') - { - consume(); - tok = Token(IMPORT, line, column); - } - else - { - tok = Token(MAP, line, column); - } - } - - if (tok.type() == EOF) - { - Exception ex(line,column); - ex << "Unexpected token"; - throw ex; - } -} - std::string DLLexer::EscapeSequence() { ostringstream oss; diff --git a/source/dllexer/dllexer.h b/source/dllexer/dllexer.h index 636f36c..dfd3701 100644 --- a/source/dllexer/dllexer.h +++ b/source/dllexer/dllexer.h @@ -6,56 +6,25 @@ typedef enum TokenTypes { - // Datatypes - ID = 0, - NUM = 1, - CHAR = 2, - STRING = 3, - SYMBOL = 4, - LIST = 5, - VECTOR = 6, - FUNC = 7, - MAP = 8, - // Symbols - LBRACK = 10, - RBRACK = 11, - LPAR = 12, - RPAR = 13, - LBRACE = 14, - RBRACE = 15, - COMMA = 16, - PIPE = 17, + PROGRAM = 0, + DEFINE = 1, + ASSIGN = 2, + LAMBDA = 3, + BEGIN = 4, + IF = 5, + APPLY = 6, + ID_LIST = 7, + EXP_LIST = 8, + LPAR = 9, + RPAR = 10, - // Operators - AND = 20, - OR = 21, - NOT = 22, - EQ = 23, - NE = 24, - LT = 25, - GT = 26, - LTE = 27, - GTE = 28, - ADD = 29, - SUB = 30, - MUL = 31, - DIV = 32, - DEFN = 33, - ASSIGN = 34, - MEMB = 35, - SEP = 36, - ARRY_IDX = 37, - MACRO = 38, - IMPORT = 39, - MUTATE = 40, - - // AST "Virtual" Node Types - PROGRAM = 50, - BLOCK = 51, - FN_CALL = 52, - PARAMS = 53, - PATT = 54, + // Datatypes + ID = 11, + NUM = 12, + CHAR = 13, + STRING = 14, + SYMBOL = 15, } eTokenTypes; typedef struct { @@ -69,7 +38,6 @@ class DLLexer : public LLNLexer { bool isWhiteSpace(void); bool isLetter(void); bool isDigit(void); - bool isOperator(void); bool isStringChar(void); void WS(void); void COMMENT(void); @@ -82,8 +50,6 @@ class DLLexer : public LLNLexer { void Char(Token& tok); void String(Token& tok); void Symbol(Token& tok); - void SingleCharOp(Token& tok); - void MultiCharOp(Token& tok); std::string EscapeSequence(); }; diff --git a/source/dlparser/dlparser.cpp b/source/dlparser/dlparser.cpp index ecd93d5..2c1eb78 100644 --- a/source/dlparser/dlparser.cpp +++ b/source/dlparser/dlparser.cpp @@ -27,156 +27,6 @@ void DLParser::parse(void) result = Program(); } -bool DLParser::isMacro( Token& token ) -{ - bool ret = false; - if( (token.type() == ID) - && (macros.find(token.text()) != macros.end()) ) - { - ret = true; - } - return ret; -} - -AST* DLParser::MacroExpansion() -{ - AST* ret = NULL; - string macro_name = lookaheadToken(1).text(); - Macro macro = macros[ macro_name ]; - std::list::iterator patt_it; - - match(ID); - for(patt_it = macro.begin(); patt_it != macro.end(); patt_it++) - { - if( speculate_MacroPatternMatch(*patt_it) ) - { - ret = MacroPatternMatch(*patt_it); - break; - } - } - - if (ret == NULL) - { - Exception ex; - ex << "Did not find a matching pattern for keyword " << macro_name << "."; - throw ex; - } - - return ret; -} - -bool DLParser::speculate_MacroPatternMatch(Pattern patt) -{ - bool success = true; - - mark(); - try - { - delete MacroPatternMatch(patt); - } - catch (Exception e) - { - success = false; - } - release(); - - return success; - -} - -AST* DLParser::MacroPatternMatch(Pattern patt) -{ - AST* ret = NULL; - std::vector params; - std::list::iterator patt_it; - - for(patt_it = patt.begin(); patt_it != patt.end(); patt_it++) - { - AST* param = NULL; - string text = lookaheadToken(1).text(); - switch( *patt_it ) - { - case MAP_TYP: - param = MapLiteral(); - break; - - case VECT_TYP: - param = VectorLiteral(); - break; - - case LIST_TYP: - param = ListLiteral(); - break; - - case BLK_TYP: - param = FuncLiteral(); - break; - - case ID_TYP: - match(ID); - param = _new AST(ID,text); - break; - - case NUM_TYP: - match(NUM); - param = _new AST(NUM,text); - break; - - case CHAR_TYP: - match(CHAR); - param = _new AST(CHAR,text); - break; - - case STR_TYP: - match(STRING); - param = _new AST(STRING,text); - break; - - case SYM_TYP: - match(SYMBOL); - param = _new AST(SYMBOL,text); - break; - - case EXPR_TYP: - param = LogicalExpr(); - break; - } - - if( !isSpeculating() ) - { - params.push_back(param); - } - else - { - delete param; - } - } - - ret = (isSpeculating()) ? _new AST(MACRO) : patt.accept( params ); - - return ret; -} - -bool DLParser::speculate_GroupExpr(void) -{ - bool success = true; - - mark(); - try - { - match(LPAR); - delete LogicalExpr(); - match(RPAR); - } - catch (Exception e) - { - success = false; - } - release(); - - return success; -} - AST* DLParser::Program(void) { AST* node = _new AST( PROGRAM ); @@ -191,396 +41,123 @@ AST* DLParser::Expression(void) { AST* ret = NULL; - if( (lookaheadType(1) == MACRO) && (lookaheadType(2) == ID)) - { - ret = MacroDefinition(); - } - else - { - ret = AssignExpr(); - } - - return ret; -} + // Expression := Application + // | Literal + // + // Application := define '(' ID Expression ')' + // | set '(' ID Expression ')' + // | lambda '(' IdList ExpList? ')' + // | begin '(' ExpList* ')' + // | if '(' Expression Expression Expression? ')' + // | ID '(' ExpList ')' + // + // ExpList := Expression+ + // + // IdList := '(' ID* ')' + // + // Literal := ID + // | CHAR + // | SYMBOL + // | STRING + // | NUMBER + + if ((ID == lookaheadType(1)) && (LPAR == lookaheadType(2))) + { + // Get the ID text + Token id = lookaheadToken(1); + std::string id_text = id.text(); + consume(); -AST* DLParser::AssignExpr(void) -{ - AST* ret = LogicalExpr(); - AST* child = NULL; - if(lookaheadType(1) == DEFN) - { - match(DEFN); - ret = new AST(DEFN, 2, ret, LogicalExpr()); - } - else if(lookaheadType(1) == ASSIGN) - { - match(ASSIGN); - child = LogicalExpr(); - if( (ret->type() != ID) && (ret->type() != ARRY_IDX) && (ret->type() != MEMB)) + match(LPAR); + if (0 == id_text.compare("define")) { - Exception ex; - ex << "Expected ID or object reference on left hand side of assignment."; - throw ex; + ret = new AST( lookaheadToken(1) ); + match(ID); + ret = new AST(DEFINE, 2, ret, Expression()); } - else if( (ret->type() == ARRY_IDX) || (ret->type() == MEMB) ) + else if (0 == id_text.compare("set")) { - AST* obj = NULL; - AST* idx = NULL; - list::iterator it = ret->children()->begin(); - obj = *it; - it++; - idx = *it; - idx->type( (ret->type() == MEMB) ? SYMBOL : idx->type() ); - ret = new AST(MUTATE, 3, obj, idx, child ); + ret = new AST( lookaheadToken(1) ); + match(ID); + ret = new AST(ASSIGN, 2, ret, Expression()); } - else + else if (0 == id_text.compare("lambda")) { - ret = new AST(ASSIGN, 2, ret, child); + ret = new AST(LAMBDA, 2, IdList(), ExpList()); } - } - return ret; -} - -AST* DLParser::LogicalExpr(void) -{ - AST* ret = NULL; - if( isMacro( lookaheadToken(1) ) ) - { - ret = MacroExpansion(); - } - else - { - ret = CompExpr(); - while((lookaheadType(1) == AND) || (lookaheadType(1) == OR)) + else if (0 == id_text.compare("begin")) { - ret = _new AST( lookaheadType(1), 1, ret); - consume(); - ret->addChild( CompExpr() ); + ret = new AST(BEGIN, 1, ExpList()); + } + else if (0 == id_text.compare("if")) + { + ret = new AST(IF, 2, Expression(), Expression()); + if(lookaheadType(1) != RPAR) + { + ret->addChild( Expression() ); + } + } + //else if (0 == id_text.compare("macro")) + //{ + //} + else + { + ret = new AST( id ); + ret = new AST(APPLY, 2, ret, ExpList()); } - } - return ret; -} - -AST* DLParser::CompExpr(void) -{ - AST* ret = AddSubExpr(); - while( (lookaheadType(1) == EQ) || (lookaheadType(1) == NE) - || (lookaheadType(1) == LT) || (lookaheadType(1) == GT) - || (lookaheadType(1) == LTE) || (lookaheadType(1) == GTE)) - { - ret = _new AST( lookaheadType(1), 1, ret); - consume(); - ret->addChild( AddSubExpr() ); - } - return ret; -} - -AST* DLParser::AddSubExpr(void) -{ - AST* ret = MulDivExpr(); - while((lookaheadType(1) == ADD) || (lookaheadType(1) == SUB)) - { - ret = _new AST( lookaheadType(1), 1, ret); - consume(); - ret->addChild( MulDivExpr() ); - } - return ret; -} - -AST* DLParser::MulDivExpr(void) -{ - AST* ret = UnaryExpr(); - while((lookaheadType(1) == MUL) || (lookaheadType(1) == DIV)) - { - ret = _new AST( lookaheadType(1), 1, ret); - consume(); - ret->addChild( UnaryExpr() ); - } - return ret; -} - -AST* DLParser::UnaryExpr(void) -{ - AST* ret = NULL; - if(lookaheadType(1) == NOT) - { - consume(); - ret = _new AST(NOT, 1, GroupExpr() ); - } - else - { - ret = GroupExpr(); - } - return ret; -} - -AST* DLParser::GroupExpr(void) -{ - AST* ret = NULL; - - if(speculate_GroupExpr()) - { - match(LPAR); - ret = LogicalExpr(); match(RPAR); } - else + else if( LPAR == lookaheadType(1) ) { - ret = MemberExpr(); - } + AST* op = NULL; + AST* operand1 = NULL; + AST* operand2 = NULL; + Token op_tok; - if( lookaheadType(1) == LPAR ) - { + // Left Operand match(LPAR); - ret = _new AST( FN_CALL, 2, ret, ExpList( LIST, RPAR ) ); - match(RPAR); - } - else if( lookaheadType(1) == LBRACK ) - { - match(LBRACK); - ret = _new AST( ARRY_IDX, 2, ret, LogicalExpr() ); - match(RBRACK); - } - - return ret; -} - -AST* DLParser::MemberExpr(void) -{ - AST* ret = NULL; - ret = Literal(); - if ( lookaheadType(1) == MEMB ) - { - match(MEMB); - ret = new AST(MEMB, 2, ret, LogicalExpr()); - } - return ret; -} - -AST* DLParser::Literal(void) -{ - AST* node = NULL; - switch(lookaheadType(1)) - { - // Literal = VectorLiteral - case LBRACK: - node = VectorLiteral(); - break; - - // Literal = ListLiteral - case LPAR: - node = ListLiteral(); - break; - - // Literal = FuncLiteral - case LBRACE: - node = FuncLiteral(); - break; - - case MAP: - node = MapLiteral(); - break; - - // Literal = ID - case ID: - node = _new AST( ID, lookaheadToken(1).text() ); - consume(); - break; + operand1 = Expression(); - // Literal = NUM - case NUM: - node = _new AST( NUM, lookaheadToken(1).text() ); - consume(); - break; - - // Literal = CHAR - case CHAR: - node = _new AST( CHAR, lookaheadToken(1).text() ); - consume(); - break; - - // Literal = STRING - case STRING: - node = _new AST( STRING, lookaheadToken(1).text() ); - consume(); - break; + // Operator + op_tok = lookaheadToken(1); + match(ID); + op = new AST(op_tok); - // Literal = SYMBOL - case SYMBOL: - node = _new AST( SYMBOL, lookaheadToken(1).text() ); - consume(); - break; + // Right Operand + operand2 = Expression(); + match(RPAR); - default: - Exception ex( lookaheadToken(1) ); - ex << "Expected literal type, recieved type " << lookaheadToken(1).type() << "."; - throw ex; + ret = new AST(APPLY, 3, op, operand1, operand2); } - return node; -} - -// MapLiteral = '{' (Literal ':' LogicalExpr)* '}' -AST* DLParser::MapLiteral(void) -{ - AST* ret = _new AST(MAP); - AST* child = NULL; - match(MAP); - match(LBRACE); - while( lookaheadType(1) != RBRACE ) + else { - child = Literal(); - match(SEP); - child = _new AST(SEP, 2, child, LogicalExpr()); - ret->addChild(child); - - if( lookaheadType(1) == COMMA ) consume(); + ret = new AST( lookaheadToken(1) ); + consume(); } - match(RBRACE); - return ret; -} -AST* DLParser::VectorLiteral(void) -{ - AST* ret = NULL; - match(LBRACK); - ret = ExpList(VECTOR, RBRACK); - match(RBRACK); return ret; } -AST* DLParser::ListLiteral(void) +AST* DLParser::ExpList(void) { - AST* ret = NULL; - match(LPAR); - ret = ExpList(LIST, RPAR); - match(RPAR); - return ret; -} - -AST* DLParser::FuncLiteral(void) -{ - AST* ret = NULL; - - match(LBRACE); - if(lookaheadType(1) == PIPE) - { - match(PIPE); - ret = ExpList(PARAMS, PIPE); - match(PIPE); - ret = _new AST(FUNC, 2, ret, ExpBlock(BLOCK,RBRACE)); - } - else + AST* ret = new AST(EXP_LIST); + while(RPAR != lookaheadType(1)) { - ret = _new AST(FUNC, 2, _new AST(PARAMS), ExpBlock(BLOCK,RBRACE)); + ret->addChild( Expression() ); } - match(RBRACE); return ret; } -// MacroDefinition = '%' ID '[' MacroPatternList ']' -AST* DLParser::MacroDefinition(void) -{ - std::list patterns; - std::string name; - - match(MACRO); - - // Get the macro's name - name = lookaheadToken(1).text(); - match(ID); - - // Parse the macro param list - match(LBRACK); - patterns = MacroPatternList(); - match(RBRACK); - - // Build and register the macro - macros.insert( std::pair(name, Macro(patterns)) ); - - return _new AST(MACRO); -} - -// MacroPatternList = MacroPattern (',' MacroPattern)* -std::list DLParser::MacroPatternList(void) +AST* DLParser::IdList(void) { - std::list patterns; - - patterns.push_back( MacroPattern() ); - while (lookaheadType(1) != RBRACK) - { - if ( lookaheadType(1) == COMMA ) - { - consume(); - if (lookaheadType(1) != RBRACK) - { - patterns.push_back( MacroPattern() ); - } - } - } - - return patterns; -} - -// MacroPattern = '(' ID+ ')' ':' LogicalExpr -Pattern DLParser::MacroPattern(void) -{ - AST* expr = NULL; - std::list pattern; - + AST* ret = new AST(ID_LIST); match(LPAR); - do + while(ID == lookaheadType(1)) { - std::string text = lookaheadToken(1).text(); - match(ID); - if( pattern_types.find(text) != pattern_types.end() ) - { - pattern.push_back( pattern_types[ text ] ); - } - else - { - Exception ex( lookaheadToken(1) ); - ex << "Unrecognized macro parameter type: " << lookaheadToken(1).text(); - throw ex; - } + ret->addChild( new AST( lookaheadToken(1) ) ); + consume(); } - while( lookaheadType(1) == ID ); match(RPAR); - match(SEP); - expr = LogicalExpr(); - - return Pattern( pattern, expr ); -} - -// ExpList = (Expression (',' Expression)*)? -AST* DLParser::ExpList(TokenType_T node_type, TokenType_T terminator) -{ - AST* node = _new AST( node_type ); - if(lookaheadType(1) != terminator) - { - node->addChild( Expression() ); - while(lookaheadType(1) != terminator) - { - if ( lookaheadType(1) == COMMA ) - { - consume(); - if (lookaheadType(1) != terminator) - { - node->addChild( Expression() ); - } - } - } - } - return node; -} - -// ExpBlock = Expression+ -AST* DLParser::ExpBlock(TokenType_T node_type, TokenType_T terminator) -{ - AST* node = _new AST(node_type); - while(lookaheadType(1) != RBRACE) - { - node->addChild( Expression() ); - } - return node; + return ret; } diff --git a/source/dlparser/dlparser.h b/source/dlparser/dlparser.h index 8fc3530..20d968e 100644 --- a/source/dlparser/dlparser.h +++ b/source/dlparser/dlparser.h @@ -19,97 +19,14 @@ class DLParser : public BTParser bool speculate_GroupExpr(void); bool speculate_MacroPatternMatch(Pattern patt); - /********************************************************************** - * EBNF Syntax Grammar - *********************************************************************/ - // Program = Expression* - // - // Expression = ID '=' LogicalExpr - // | MacroDefinition - // | $MacroExpansion$ - // | LogicalExpr - // - // AssignExpr = LogicalExpr '=' LogicalExpr - // - // LogicalExpr = CompExpr (('&&' | '||') CompExpr)* - // - // CompExpr = AddSubExpr (('==' | '!=' | '<' | '>' | '<=' | '>=') AddSubExpr)* - // - // AddSubExpr = MulDivExpr (('+' | '-') MulDivExpr)* - // - // MulDivExpr = UnaryExpr (('*' | '/') UnaryExpr)* - // - // UnaryExpr = '!' GroupExpr - // | GroupExpr - // - // GroupExpr = '(' LogicalExpr ')' - // | '(' LogicalExpr ')' '(' ExpList ')' - // | '(' LogicalExpr ')' '[' LogicalExpr ']' - // | Literal - // | Literal '(' ExpList ')' - // | Literal '[' LogicalExpr ']' - // - // MemberExpr = Literal '.' LogicalExpr - // - // Literal = VectorLiteral - // | ListLiteral - // | FuncLiteral - // | ID - // | NUM - // | CHAR - // | STRING - // | SYMBOL - // - // MapLiteral = '{' (Literal ':' AssignExpr)* '}' - // - // VectorLiteral = '[' ExpList ']' - // - // ListLiteral = '(' ExpList ')' - // - // FuncLiteral = '{' ExpBlock '}' - // | '{' '|' ExpList '|' ExpBlock '}' - // - // MacroDefinition = '%' ID '[' MacroParamList ']' - // - // MacroPatternList = MacroPattern (',' MacroPattern)* - // - // MacroPattern = '(' ID+ ')' ':' LogicalExpr - // - // ExpList = (GroupExpr (',' GroupExpr)*)? - // - // ExpBlock = Expression* private: // Entry Rules AST* Program(void); - - // Order of Precedence rules for expressions AST* Expression(void); - AST* AssignExpr(void); - AST* LogicalExpr(void); - AST* CompExpr(void); - AST* AddSubExpr(void); - AST* MulDivExpr(void); - AST* UnaryExpr(void); - AST* GroupExpr(void); - AST* MemberExpr(void); - - // Literal Type Rules + AST* Application(void); AST* Literal(void); - AST* MapLiteral(void); - AST* VectorLiteral(void); - AST* ListLiteral(void); - AST* FuncLiteral(void); - - // Macro Rules - AST* MacroDefinition(void); - std::list MacroPatternList(void); - Pattern MacroPattern(void); - AST* MacroExpansion(); - AST* MacroPatternMatch(Pattern patt); - - // Helper rules for lists and blocks of expressions - AST* ExpList(TokenType_T node_type, TokenType_T terminator); - AST* ExpBlock(TokenType_T node_type, TokenType_T terminator); + AST* ExpList(void); + AST* IdList(void); }; #endif diff --git a/source/main.cpp b/source/main.cpp index 15e6842..bc55de8 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -7,6 +7,7 @@ #include "common.h" #include "macro.h" #include "options.h" +#include "astprinter.h" using namespace std; @@ -31,8 +32,9 @@ int main(int argc, char** argv) // Setup Parser and Visitors DLParser parser; - Scheme printer(output); - Scheme debug_printer(std::cout); + //Scheme printer(output); + //Scheme debug_printer(std::cout); + ASTPrinter debug_printer; parser.input(new DLLexer(input)); // Parse the input stream @@ -40,16 +42,17 @@ int main(int argc, char** argv) // Post process the AST (converts to scheme and prints to output file) parser.process( debug_printer ); - parser.process( printer ); + //parser.process( printer ); // Close the output file output.close(); // Compile the temporary file with chicken scheme - system( string("csc -O5 -v " + temp_fname).c_str() ); + //system( string("csc -O5 -v " + temp_fname).c_str() ); + (void)temp_fname; - cout << "Removing temporary files..." << endl; - (void)remove( temp_fname.c_str() ); + //cout << "Removing temporary files..." << endl; + //(void)remove( temp_fname.c_str() ); } else { diff --git a/source/visitors/scheme/scheme.cpp b/source/visitors/scheme/scheme.cpp index 8bd10a9..0899262 100644 --- a/source/visitors/scheme/scheme.cpp +++ b/source/visitors/scheme/scheme.cpp @@ -23,69 +23,69 @@ string Scheme::typeToString(ASTNodeType type) switch (type) { - case ID: - ret << "ID "; break; - case NUM: - ret << "NUM "; break; - case MAP: - ret << "MAP "; break; - case CHAR: - ret << "CHAR "; break; - case ADD: - ret << "+ "; break; - case SUB: - ret << "- "; break; - case MUL: - ret << "* "; break; - case DIV: - ret << "/ "; break; - case AND: - ret << "and "; break; - case OR: - ret << "or "; break; - case NOT: - ret << "not "; break; - case EQ: - ret << "equal? "; break; - case NE: - ret << "NE "; break; - case LT: - ret << "< "; break; - case GT: - ret << "> "; break; - case LTE: - ret << "<= "; break; - case GTE: - ret << ">= "; break; - case DEFN: - ret << "define "; break; - case ASSIGN: - ret << "set! "; break; - case MUTATE: - ret << "obj-set! "; break; - case PROGRAM: - ret << "begin "; break; - case VECTOR: - ret << "vector "; break; - case LIST: - ret << "list "; break; - case BLOCK: - ret << "begin "; break; - case FUNC: - ret << "lambda "; break; - case FN_CALL: - ret << "apply "; break; - case ARRY_IDX: - ret << "ARRY_IDX "; break; - case SEP: - ret << "cons "; break; - case MEMB: - ret << "hash-table-ref "; break; - - // Print nothing for the following nodes - case MACRO: - case PARAMS: - break; + //case ID: + // ret << "ID "; break; + //case NUM: + // ret << "NUM "; break; + //case MAP: + // ret << "MAP "; break; + //case CHAR: + // ret << "CHAR "; break; + //case ADD: + // ret << "+ "; break; + //case SUB: + // ret << "- "; break; + //case MUL: + // ret << "* "; break; + //case DIV: + // ret << "/ "; break; + //case AND: + // ret << "and "; break; + //case OR: + // ret << "or "; break; + //case NOT: + // ret << "not "; break; + //case EQ: + // ret << "equal? "; break; + //case NE: + // ret << "NE "; break; + //case LT: + // ret << "< "; break; + //case GT: + // ret << "> "; break; + //case LTE: + // ret << "<= "; break; + //case GTE: + // ret << ">= "; break; + //case DEFN: + // ret << "define "; break; + //case ASSIGN: + // ret << "set! "; break; + //case MUTATE: + // ret << "obj-set! "; break; + //case PROGRAM: + // ret << "begin "; break; + //case VECTOR: + // ret << "vector "; break; + //case LIST: + // ret << "list "; break; + //case BLOCK: + // ret << "begin "; break; + //case FUNC: + // ret << "lambda "; break; + //case FN_CALL: + // ret << "apply "; break; + //case ARRY_IDX: + // ret << "ARRY_IDX "; break; + //case SEP: + // ret << "cons "; break; + //case MEMB: + // ret << "hash-table-ref "; break; + + //// Print nothing for the following nodes + //case MACRO: + //case PARAMS: + // break; // Print out the type id (this will probably cause an error but also // alert us to the fact that it is not properly handled) @@ -108,7 +108,7 @@ void Scheme::afterVisit(AST* cur, int depth) void Scheme::beforeChildren(AST* cur, int depth) { nodeTypeBeginAction(cur); - if( cur->type() != MACRO ) + //if( cur->type() != MACRO ) { if( isDatatype( cur->type() ) ) { @@ -124,7 +124,7 @@ void Scheme::beforeChildren(AST* cur, int depth) void Scheme::afterChildren(AST* cur, int depth) { nodeTypeEndAction(cur); - if( !isDatatype( cur->type() ) && (cur->type() != MACRO)) + if( !isDatatype( cur->type() ) ) { stream << ")"; } @@ -237,21 +237,21 @@ void Scheme::nodeTypeBeginAction(AST* cur) std::string text = cur->text(); switch( cur->type() ) { - case MEMB: - cur->children()->back()->type( SYMBOL ); - break; + // case MEMB: + // cur->children()->back()->type( SYMBOL ); + // break; - case BLOCK: - scope_stack.startScope(); - break; + // case BLOCK: + // scope_stack.startScope(); + // break; - case DEFN: - defineSymbol(cur); - break; + // case DEFN: + // defineSymbol(cur); + // break; - case ASSIGN: - assignSymbol(cur); - break; + // case ASSIGN: + // assignSymbol(cur); + // break; //TODO: Define builtin symbols and enable adding function args to scope //case ID: @@ -267,9 +267,9 @@ void Scheme::nodeTypeEndAction(AST* cur) { switch( cur->type() ) { - case BLOCK: - scope_stack.stopScope(); - break; + // case BLOCK: + // scope_stack.stopScope(); + // break; default: break; diff --git a/tests/test_dllexer.cpp b/tests/test_dllexer.cpp index 93c64cf..9c0b6bf 100644 --- a/tests/test_dllexer.cpp +++ b/tests/test_dllexer.cpp @@ -57,7 +57,7 @@ void TestLexerThrowsException(std::string& input) namespace { //------------------------------------------------------------------------- - // Recognize Individual Operators + // Recognize and Ignore Whitespace //------------------------------------------------------------------------- TEST(Recognize_And_Ignore_Whitespace) { @@ -67,7 +67,7 @@ namespace { } //------------------------------------------------------------------------- - // Recognize Individual Operators + // Recognize and Ignore Comments //------------------------------------------------------------------------- TEST(Recognize_And_Ignore_Comments) { @@ -85,7 +85,7 @@ namespace { } //------------------------------------------------------------------------- - // Recognize Individual Operators + // Recognize Valid IDs //------------------------------------------------------------------------- TEST(Recognize_Valid_IDs) { @@ -182,205 +182,6 @@ namespace { TestLexerWithInput( input, expected ); } - //------------------------------------------------------------------------- - // Test Individual Operators - //------------------------------------------------------------------------- - TEST(Recognize_Left_Bracket) - { - std::string input("["); - eTokenTypes expected[] = { LBRACK, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Right_Bracket) - { - std::string input("]"); - eTokenTypes expected[] = { RBRACK, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Left_Paren) - { - std::string input("("); - eTokenTypes expected[] = { LPAR, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Right_Paren) - { - std::string input(")"); - eTokenTypes expected[] = { RPAR, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Left_Brace) - { - std::string input("{"); - eTokenTypes expected[] = { LBRACE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Right_Brace) - { - std::string input("}"); - eTokenTypes expected[] = { RBRACE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Comma) - { - std::string input(","); - eTokenTypes expected[] = { COMMA, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Addition_Op) - { - std::string input("+"); - eTokenTypes expected[] = { ADD, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Multiplication_Op) - { - std::string input("*"); - eTokenTypes expected[] = { MUL, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Division_Op) - { - std::string input("/"); - eTokenTypes expected[] = { DIV, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Member_Accessor_Op) - { - std::string input("."); - eTokenTypes expected[] = { MEMB, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Macro_Op) - { - std::string input("%"); - eTokenTypes expected[] = { MACRO, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Subtraction_Op) - { - std::string input("-"); - eTokenTypes expected[] = { SUB, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Assignment_Op) - { - std::string input("="); - eTokenTypes expected[] = { ASSIGN, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Equal_Comparison_Op) - { - std::string input("=="); - eTokenTypes expected[] = { EQ, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Not_Op) - { - std::string input("!"); - eTokenTypes expected[] = { NOT, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Not_Equal_Op) - { - std::string input("!="); - eTokenTypes expected[] = { NE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Less_Than_Op) - { - std::string input("<"); - eTokenTypes expected[] = { LT, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Less_Than_Equal_Op) - { - std::string input("<="); - eTokenTypes expected[] = { LTE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Greater_Than_Op) - { - std::string input(">"); - eTokenTypes expected[] = { GT, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Greater_Than_Or_Equal_Op) - { - std::string input(">="); - eTokenTypes expected[] = { GTE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Pipe) - { - std::string input("|"); - eTokenTypes expected[] = { PIPE, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Or_Op) - { - std::string input("||"); - eTokenTypes expected[] = { OR, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_And_Op) - { - std::string input("&&"); - eTokenTypes expected[] = { AND, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Seperator) - { - std::string input(":"); - eTokenTypes expected[] = { SEP, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Definition_Op) - { - std::string input(":="); - eTokenTypes expected[] = { DEFN, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Map_Op) - { - std::string input("@"); - eTokenTypes expected[] = { MAP, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - - TEST(Recognize_Import_Op) - { - std::string input("@="); - eTokenTypes expected[] = { IMPORT, (eTokenTypes)EOF }; - TestLexerWithInput( input, expected ); - } - //------------------------------------------------------------------------- // Test Exceptional Cases //------------------------------------------------------------------------- @@ -398,14 +199,6 @@ namespace { std::string num_exception4("1.a"); TestLexerThrowsException( num_exception4 ); - - // Make sure we throw an exception for an invalid operator - std::string op_exception1("^"); - TestLexerThrowsException( op_exception1 ); - - // Make sure we throw an exception for an invalid operator - std::string multi_op_exception1("&"); - TestLexerThrowsException( multi_op_exception1 ); } //------------------------------------------------------------------------- @@ -420,8 +213,8 @@ namespace { TEST(Handle_Recognition_At_The_End_Of_Input) { - std::string input("["); - eTokenTypes expected[] = { LBRACK, (eTokenTypes)EOF }; + std::string input("a"); + eTokenTypes expected[] = { ID, (eTokenTypes)EOF }; TestLexerWithInput( input, expected ); } diff --git a/tests/test_dlparser.cpp b/tests/test_dlparser.cpp index 1b0e356..44aa96e 100644 --- a/tests/test_dlparser.cpp +++ b/tests/test_dlparser.cpp @@ -68,882 +68,882 @@ void TestParserThrowsException(std::string& input) // Begin Unit Tests //----------------------------------------------------------------------------- namespace { - //------------------------------------------------------------------------- - // Test Parsing of Data Type Literals - //------------------------------------------------------------------------- - - // Vector Literals - //---------------- - TEST(Parse_An_Empty_Vector) - { - std::string input("[]"); - eTokenTypes expected[] = { - VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_An_Vector_With_One_Item) - { - std::string input("[1]"); - eTokenTypes expected[] = { - NUM, VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Vector_Of_Two_Items) - { - std::string input("[1,2]"); - eTokenTypes expected[] = { - NUM, NUM, VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Vector_Of_Three_Items) - { - std::string input("[1,2,3]"); - eTokenTypes expected[] = { - NUM, NUM, NUM, VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Vector_With_Trailing_Commas) - { - std::string input("[1,]"); - eTokenTypes expected[] = { - NUM, VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // List Literals - //-------------- - TEST(Parse_A_List) - { - std::string input("()"); - eTokenTypes expected[] = { - LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_An_List_With_One_Item) - { - std::string input("(1,)"); // Comma is required here - eTokenTypes expected[] = { - NUM, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_List_Of_Two_Items) - { - std::string input("(1,2)"); - eTokenTypes expected[] = { - NUM, NUM, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_List_Of_Three_Items) - { - std::string input("(1,2,3)"); - eTokenTypes expected[] = { - NUM, NUM, NUM, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_List_With_Trailing_Commas) - { - std::string input("(1,)"); - eTokenTypes expected[] = { - NUM, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_List_With_Heterogeneous_Elements) - { - std::string input("(1,$foo,bar)"); - eTokenTypes expected[] = { - NUM, SYMBOL, ID, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Block Literals - //--------------- - TEST(Parse_A_Block_With_No_Parameters) - { - std::string input("{}"); - eTokenTypes expected[] = { - PARAMS, BLOCK, FUNC, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Block_With_One_Param) - { - std::string input("{|a|}"); - eTokenTypes expected[] = { - ID, PARAMS, BLOCK, FUNC, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Block_With_Two_Params) - { - std::string input("{|a,b|}"); - eTokenTypes expected[] = { - ID, ID, PARAMS, BLOCK, FUNC, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Block_With_Two_Params_That_Performs_An_Addition_Operation) - { - std::string input("{|a,b| a + b}"); - eTokenTypes expected[] = { - ID, ID, PARAMS, ID, ID, ADD, BLOCK, FUNC, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Map Literals - //------------- - TEST(Parse_An_Empty_Map) - { - std::string input("@{}"); - eTokenTypes expected[] = { - MAP, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Map_With_One_Entry) - { - std::string input("@{ $foo : 42 }"); - eTokenTypes expected[] = { - SYMBOL, NUM, SEP, MAP, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Map_With_Two_Entries) - { - std::string input("@{ $foo : 42, $bar : 42 }"); - eTokenTypes expected[] = { - SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Maps_Should_Allow_A_Trailing_Comma) - { - std::string input("@{ $foo : 42, $bar : 42, }"); - eTokenTypes expected[] = { - SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Id Literals - //------------ - TEST(Parse_An_Id) - { - std::string input("foo"); - eTokenTypes expected[] = { - ID, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Number Literals - //---------------- - TEST(Parse_A_Num) - { - std::string input("42"); - eTokenTypes expected[] = { - NUM, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Character Literals - //------------------- - TEST(Parse_A_Char) - { - std::string input("'a'"); - eTokenTypes expected[] = { - CHAR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // String Literals - //---------------- - TEST(Parse_A_String) - { - std::string input("\"\""); - eTokenTypes expected[] = { - STRING, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Symbol Literals - //---------------- - TEST(Parse_A_Symbol) - { - std::string input("$foo"); - eTokenTypes expected[] = { - SYMBOL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - //------------------------------------------------------------------------- - // Test Operators And Operator Precedence - //------------------------------------------------------------------------- - - // Member Accessor - //---------------- - TEST(Parse_A_Member_Acces_One_Level_Deep) - { - std::string input("foo.bar"); - eTokenTypes expected[] = { - ID, ID, MEMB, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Member_Acces_Two_Levels_Deep) - { - std::string input("foo.bar.somethin"); - eTokenTypes expected[] = { - ID, ID, ID, MEMB, MEMB, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Grouping Expression - //-------------------- - TEST(Parse_A_Grouping_Expression) - { - std::string input("( 1 + 1 )"); - eTokenTypes expected[] = { - NUM, NUM, ADD, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Grouping_Expression_With_A_Lower_Priority_Statement) - { - std::string input("(1 + 2) * 3"); - eTokenTypes expected[] = { - NUM, NUM, ADD, NUM, MUL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Grouping_Expression_With_A_Higher_Priority_Statement) - { - std::string input("1 + (2 * 3)"); - eTokenTypes expected[] = { - NUM, NUM, NUM, MUL, ADD, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Function Application - //--------------------- - TEST(Parse_A_Simple_Function_Application) - { - std::string input("foo()"); - eTokenTypes expected[] = { - ID, LIST, FN_CALL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Collection Access - //------------------ - TEST(Parse_An_Array_Indexing_Expression) - { - std::string input("foo[1]"); - eTokenTypes expected[] = { - ID, NUM, ARRY_IDX, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Logical Operators - //------------------ - TEST(Parse_A_Logical_And_Operation) - { - std::string input("foo && bar"); - eTokenTypes expected[] = { - ID, ID, AND, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Logical_Or_Operation) - { - std::string input("foo || bar"); - eTokenTypes expected[] = { - ID, ID, OR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Logical_Not_Operation) - { - std::string input("! foo"); - eTokenTypes expected[] = { - ID, NOT, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Arithmetic Operators - //--------------------- - TEST(Parse_An_Addition_Operation) - { - std::string input("foo + bar"); - eTokenTypes expected[] = { - ID, ID, ADD, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Subtraction_Operation) - { - std::string input("foo - bar"); - eTokenTypes expected[] = { - ID, ID, SUB, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Multiplication_Operation) - { - std::string input("foo * bar"); - eTokenTypes expected[] = { - ID, ID, MUL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Division_Operation) - { - std::string input("foo / bar"); - eTokenTypes expected[] = { - ID, ID, DIV, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Comparison Operators - //--------------------- - TEST(Parse_An_Equal_Operation) - { - std::string input("foo == bar"); - eTokenTypes expected[] = { - ID, ID, EQ, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Not_Equal_Operation) - { - std::string input("foo != bar"); - eTokenTypes expected[] = { - ID, ID, NE, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Less_Than_Operation) - { - std::string input("foo < bar"); - eTokenTypes expected[] = { - ID, ID, LT, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Greater_Than_Operation) - { - std::string input("foo > bar"); - eTokenTypes expected[] = { - ID, ID, GT, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Less_Than_Or_Equal_Operation) - { - std::string input("foo <= bar"); - eTokenTypes expected[] = { - ID, ID, LTE, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Greater_Than_Or_Equal_Operation) - { - std::string input("foo >= bar"); - eTokenTypes expected[] = { - ID, ID, GTE, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Definition and Assignment - //-------------------------- - TEST(Parse_A_Definition_Operation) - { - std::string input("foo := 1"); - eTokenTypes expected[] = { - ID, NUM, DEFN, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_An_Assignment_Operation) - { - std::string input("foo = bar"); - eTokenTypes expected[] = { - ID, ID, ASSIGN, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_An_Assignment_To_An_Array_Member) - { - std::string input("foo[1] = bar"); - eTokenTypes expected[] = { - ID, NUM, ID, MUTATE, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_An_Assignment_To_A_Map_Member) - { - std::string input("foo[\"bar\"] = bar"); - eTokenTypes expected[] = { - ID, STRING, ID, MUTATE, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - //------------------------------------------------------------------------- - // Test Macro Definition and Expansion - //------------------------------------------------------------------------- - - // Map - //---- - TEST(Parse_A_Macro_Taking_One_Map) - { - std::string input("\% foo [ (M) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Map_Parameter) - { - std::string input( - "\% foo [ (M) : $1 ]\n" - "foo @{}" - ); - eTokenTypes expected[] = { - MACRO, - MAP, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Vector - //------- - TEST(Parse_A_Macro_Taking_One_Vector) - { - std::string input("\% foo [ (V) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Vector_Parameter) - { - std::string input( - "\% foo [ (V) : $1 ]\n" - "foo []" - ); - eTokenTypes expected[] = { - MACRO, - VECTOR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // List - //----- - TEST(Parse_A_Macro_Taking_One_List) - { - std::string input("\% foo [ (L) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_List_Parameter) - { - std::string input( - "\% foo [ (L) : $1 ]\n" - "foo ()" - ); - eTokenTypes expected[] = { - MACRO, - LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Block - //------ - TEST(Parse_A_Macro_Taking_One_Block) - { - std::string input("\% foo [ (B) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Block_Parameter) - { - std::string input( - "\% foo [ (B) : $1 ]\n" - "foo {}" - ); - eTokenTypes expected[] = { - MACRO, - PARAMS, BLOCK, FUNC, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Id - //--- - TEST(Parse_A_Macro_taking_One_Id) - { - std::string input("\% foo [ (I) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Id_Parameter) - { - std::string input( - "\% foo [ (I) : $1 ]\n" - "foo bar" - ); - eTokenTypes expected[] = { - MACRO, - ID, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Number - //------- - TEST(Parse_A_Macro_Taking_One_Number) - { - std::string input("\% foo [ (N) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Number_Parameter) - { - std::string input( - "\% foo [ (N) : $1 ]\n" - "foo 1.0" - ); - eTokenTypes expected[] = { - MACRO, - NUM, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Character - //---------- - TEST(Parse_A_Macro_Taking_One_Character) - { - std::string input("\% foo [ (C) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Character_Parameter) - { - std::string input( - "\% foo [ (C) : $1 ]\n" - "foo 'a'" - ); - eTokenTypes expected[] = { - MACRO, - CHAR, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // String - //------- - TEST(Parse_A_Macro_Taking_One_String) - { - std::string input("\% foo [ (St) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_String_Parameter) - { - std::string input( - "\% foo [ (St) : $1 ]\n" - "foo \"\"" - ); - eTokenTypes expected[] = { - MACRO, - STRING, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Symbol - //------- - TEST(Parse_A_Macro_Taking_One_Symbol) - { - std::string input("\% foo [ (Sy) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Symbol_Parameter) - { - std::string input( - "\% foo [ (Sy) : $1 ]\n" - "foo $bar" - ); - eTokenTypes expected[] = { - MACRO, - SYMBOL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Expression - //----------- - TEST(Parse_A_Macro_Taking_One_Expression) - { - std::string input("\% foo [ (E) : $1 ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_A_Expression_Parameter) - { - std::string input( - "\% foo [ (E) : $1 ]\n" - "foo 1 + 1" - ); - eTokenTypes expected[] = { - MACRO, - NUM, NUM, ADD, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - // Corner Cases - //------------- - TEST(Throw_Exception_When_Invalid_Macro_Param_Type_Used) - { - std::string input("\% foo [ (Z) : $1 ]"); - TestParserThrowsException(input); - } - - TEST(Throw_Exception_When_No_Macro_Pattern_Matches) - { - std::string input( - "\% foo [ (I) : $1 ]\n" - "foo 1.0" //Expecting and ID but a number is given - ); - TestParserThrowsException(input); - } - - TEST(Parse_A_Macro_With_Multiple_Parameter_Types) - { - std::string input("\% tuple [ (E E) : ($1,$2) ]"); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_Multiple_Parameter_Types) - { - std::string input( - "\% tuple [ (E E) : ($1,$2) ]\n" - "tuple 1.0 'a'" - ); - eTokenTypes expected[] = { - MACRO, - NUM, CHAR, LIST, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Parse_A_Macro_With_Multiple_Patterns) - { - std::string input( - // Emulate an If statement - "\% if [\n" - " (E B B) : exec_if($1,$2,$3),\n" - " (E B) : exec_if($1,$2)\n" - "]" - ); - eTokenTypes expected[] = { - MACRO, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - TEST(Use_A_Macro_With_Multiple_Patterns) - { - std::string input( - // Emulate an If statement - "\% if [\n" - " (E B B) : exec_if($1,$2,$3),\n" - " (E B) : exec_if($1,$2)\n" - "]\n" - "if (1 == 1) {}\n" - "if (1 == 1) {} {}\n" - ); - eTokenTypes expected[] = { - MACRO, - ID, NUM, NUM, EQ, PARAMS, BLOCK, FUNC, LIST, FN_CALL, - ID, NUM, NUM, EQ, PARAMS, BLOCK, FUNC, PARAMS, BLOCK, FUNC, LIST, FN_CALL, - PROGRAM - }; - TestParserWithInput( input, expected ); - } - - //------------------------------------------------------------------------- - // Test General Corner Cases - //------------------------------------------------------------------------- - TEST(Parse_An_Empty_Program) - { - std::string input(""); - eTokenTypes expected[] = { PROGRAM }; - TestParserWithInput( input, expected ); - } - - TEST(Throw_Exception_When_Literal_On_Left_Side_Of_Assignment) - { - std::string input("[] = 5"); - TestParserThrowsException(input); - } + ////------------------------------------------------------------------------- + //// Test Parsing of Data Type Literals + ////------------------------------------------------------------------------- + + //// Vector Literals + ////---------------- + //TEST(Parse_An_Empty_Vector) + //{ + // std::string input("[]"); + // eTokenTypes expected[] = { + // VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_An_Vector_With_One_Item) + //{ + // std::string input("[1]"); + // eTokenTypes expected[] = { + // NUM, VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Vector_Of_Two_Items) + //{ + // std::string input("[1,2]"); + // eTokenTypes expected[] = { + // NUM, NUM, VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Vector_Of_Three_Items) + //{ + // std::string input("[1,2,3]"); + // eTokenTypes expected[] = { + // NUM, NUM, NUM, VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Vector_With_Trailing_Commas) + //{ + // std::string input("[1,]"); + // eTokenTypes expected[] = { + // NUM, VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// List Literals + ////-------------- + //TEST(Parse_A_List) + //{ + // std::string input("()"); + // eTokenTypes expected[] = { + // LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_An_List_With_One_Item) + //{ + // std::string input("(1,)"); // Comma is required here + // eTokenTypes expected[] = { + // NUM, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_List_Of_Two_Items) + //{ + // std::string input("(1,2)"); + // eTokenTypes expected[] = { + // NUM, NUM, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_List_Of_Three_Items) + //{ + // std::string input("(1,2,3)"); + // eTokenTypes expected[] = { + // NUM, NUM, NUM, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_List_With_Trailing_Commas) + //{ + // std::string input("(1,)"); + // eTokenTypes expected[] = { + // NUM, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_List_With_Heterogeneous_Elements) + //{ + // std::string input("(1,$foo,bar)"); + // eTokenTypes expected[] = { + // NUM, SYMBOL, ID, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Block Literals + ////--------------- + //TEST(Parse_A_Block_With_No_Parameters) + //{ + // std::string input("{}"); + // eTokenTypes expected[] = { + // PARAMS, BLOCK, FUNC, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Block_With_One_Param) + //{ + // std::string input("{|a|}"); + // eTokenTypes expected[] = { + // ID, PARAMS, BLOCK, FUNC, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Block_With_Two_Params) + //{ + // std::string input("{|a,b|}"); + // eTokenTypes expected[] = { + // ID, ID, PARAMS, BLOCK, FUNC, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Block_With_Two_Params_That_Performs_An_Addition_Operation) + //{ + // std::string input("{|a,b| a + b}"); + // eTokenTypes expected[] = { + // ID, ID, PARAMS, ID, ID, ADD, BLOCK, FUNC, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Map Literals + ////------------- + //TEST(Parse_An_Empty_Map) + //{ + // std::string input("@{}"); + // eTokenTypes expected[] = { + // MAP, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Map_With_One_Entry) + //{ + // std::string input("@{ $foo : 42 }"); + // eTokenTypes expected[] = { + // SYMBOL, NUM, SEP, MAP, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Map_With_Two_Entries) + //{ + // std::string input("@{ $foo : 42, $bar : 42 }"); + // eTokenTypes expected[] = { + // SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Maps_Should_Allow_A_Trailing_Comma) + //{ + // std::string input("@{ $foo : 42, $bar : 42, }"); + // eTokenTypes expected[] = { + // SYMBOL, NUM, SEP, SYMBOL, NUM, SEP, MAP, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Id Literals + ////------------ + //TEST(Parse_An_Id) + //{ + // std::string input("foo"); + // eTokenTypes expected[] = { + // ID, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Number Literals + ////---------------- + //TEST(Parse_A_Num) + //{ + // std::string input("42"); + // eTokenTypes expected[] = { + // NUM, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Character Literals + ////------------------- + //TEST(Parse_A_Char) + //{ + // std::string input("'a'"); + // eTokenTypes expected[] = { + // CHAR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// String Literals + ////---------------- + //TEST(Parse_A_String) + //{ + // std::string input("\"\""); + // eTokenTypes expected[] = { + // STRING, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Symbol Literals + ////---------------- + //TEST(Parse_A_Symbol) + //{ + // std::string input("$foo"); + // eTokenTypes expected[] = { + // SYMBOL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + ////------------------------------------------------------------------------- + //// Test Operators And Operator Precedence + ////------------------------------------------------------------------------- + + //// Member Accessor + ////---------------- + //TEST(Parse_A_Member_Acces_One_Level_Deep) + //{ + // std::string input("foo.bar"); + // eTokenTypes expected[] = { + // ID, ID, MEMB, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Member_Acces_Two_Levels_Deep) + //{ + // std::string input("foo.bar.somethin"); + // eTokenTypes expected[] = { + // ID, ID, ID, MEMB, MEMB, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Grouping Expression + ////-------------------- + //TEST(Parse_A_Grouping_Expression) + //{ + // std::string input("( 1 + 1 )"); + // eTokenTypes expected[] = { + // NUM, NUM, ADD, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Grouping_Expression_With_A_Lower_Priority_Statement) + //{ + // std::string input("(1 + 2) * 3"); + // eTokenTypes expected[] = { + // NUM, NUM, ADD, NUM, MUL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Grouping_Expression_With_A_Higher_Priority_Statement) + //{ + // std::string input("1 + (2 * 3)"); + // eTokenTypes expected[] = { + // NUM, NUM, NUM, MUL, ADD, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Function Application + ////--------------------- + //TEST(Parse_A_Simple_Function_Application) + //{ + // std::string input("foo()"); + // eTokenTypes expected[] = { + // ID, LIST, FN_CALL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Collection Access + ////------------------ + //TEST(Parse_An_Array_Indexing_Expression) + //{ + // std::string input("foo[1]"); + // eTokenTypes expected[] = { + // ID, NUM, ARRY_IDX, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Logical Operators + ////------------------ + //TEST(Parse_A_Logical_And_Operation) + //{ + // std::string input("foo && bar"); + // eTokenTypes expected[] = { + // ID, ID, AND, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Logical_Or_Operation) + //{ + // std::string input("foo || bar"); + // eTokenTypes expected[] = { + // ID, ID, OR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Logical_Not_Operation) + //{ + // std::string input("! foo"); + // eTokenTypes expected[] = { + // ID, NOT, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Arithmetic Operators + ////--------------------- + //TEST(Parse_An_Addition_Operation) + //{ + // std::string input("foo + bar"); + // eTokenTypes expected[] = { + // ID, ID, ADD, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Subtraction_Operation) + //{ + // std::string input("foo - bar"); + // eTokenTypes expected[] = { + // ID, ID, SUB, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Multiplication_Operation) + //{ + // std::string input("foo * bar"); + // eTokenTypes expected[] = { + // ID, ID, MUL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Division_Operation) + //{ + // std::string input("foo / bar"); + // eTokenTypes expected[] = { + // ID, ID, DIV, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Comparison Operators + ////--------------------- + //TEST(Parse_An_Equal_Operation) + //{ + // std::string input("foo == bar"); + // eTokenTypes expected[] = { + // ID, ID, EQ, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Not_Equal_Operation) + //{ + // std::string input("foo != bar"); + // eTokenTypes expected[] = { + // ID, ID, NE, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Less_Than_Operation) + //{ + // std::string input("foo < bar"); + // eTokenTypes expected[] = { + // ID, ID, LT, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Greater_Than_Operation) + //{ + // std::string input("foo > bar"); + // eTokenTypes expected[] = { + // ID, ID, GT, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Less_Than_Or_Equal_Operation) + //{ + // std::string input("foo <= bar"); + // eTokenTypes expected[] = { + // ID, ID, LTE, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Greater_Than_Or_Equal_Operation) + //{ + // std::string input("foo >= bar"); + // eTokenTypes expected[] = { + // ID, ID, GTE, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Definition and Assignment + ////-------------------------- + //TEST(Parse_A_Definition_Operation) + //{ + // std::string input("foo := 1"); + // eTokenTypes expected[] = { + // ID, NUM, DEFN, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_An_Assignment_Operation) + //{ + // std::string input("foo = bar"); + // eTokenTypes expected[] = { + // ID, ID, ASSIGN, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_An_Assignment_To_An_Array_Member) + //{ + // std::string input("foo[1] = bar"); + // eTokenTypes expected[] = { + // ID, NUM, ID, MUTATE, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_An_Assignment_To_A_Map_Member) + //{ + // std::string input("foo[\"bar\"] = bar"); + // eTokenTypes expected[] = { + // ID, STRING, ID, MUTATE, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + ////------------------------------------------------------------------------- + //// Test Macro Definition and Expansion + ////------------------------------------------------------------------------- + + //// Map + ////---- + //TEST(Parse_A_Macro_Taking_One_Map) + //{ + // std::string input("\% foo [ (M) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Map_Parameter) + //{ + // std::string input( + // "\% foo [ (M) : $1 ]\n" + // "foo @{}" + // ); + // eTokenTypes expected[] = { + // MACRO, + // MAP, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Vector + ////------- + //TEST(Parse_A_Macro_Taking_One_Vector) + //{ + // std::string input("\% foo [ (V) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Vector_Parameter) + //{ + // std::string input( + // "\% foo [ (V) : $1 ]\n" + // "foo []" + // ); + // eTokenTypes expected[] = { + // MACRO, + // VECTOR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// List + ////----- + //TEST(Parse_A_Macro_Taking_One_List) + //{ + // std::string input("\% foo [ (L) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_List_Parameter) + //{ + // std::string input( + // "\% foo [ (L) : $1 ]\n" + // "foo ()" + // ); + // eTokenTypes expected[] = { + // MACRO, + // LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Block + ////------ + //TEST(Parse_A_Macro_Taking_One_Block) + //{ + // std::string input("\% foo [ (B) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Block_Parameter) + //{ + // std::string input( + // "\% foo [ (B) : $1 ]\n" + // "foo {}" + // ); + // eTokenTypes expected[] = { + // MACRO, + // PARAMS, BLOCK, FUNC, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Id + ////--- + //TEST(Parse_A_Macro_taking_One_Id) + //{ + // std::string input("\% foo [ (I) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Id_Parameter) + //{ + // std::string input( + // "\% foo [ (I) : $1 ]\n" + // "foo bar" + // ); + // eTokenTypes expected[] = { + // MACRO, + // ID, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Number + ////------- + //TEST(Parse_A_Macro_Taking_One_Number) + //{ + // std::string input("\% foo [ (N) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Number_Parameter) + //{ + // std::string input( + // "\% foo [ (N) : $1 ]\n" + // "foo 1.0" + // ); + // eTokenTypes expected[] = { + // MACRO, + // NUM, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Character + ////---------- + //TEST(Parse_A_Macro_Taking_One_Character) + //{ + // std::string input("\% foo [ (C) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Character_Parameter) + //{ + // std::string input( + // "\% foo [ (C) : $1 ]\n" + // "foo 'a'" + // ); + // eTokenTypes expected[] = { + // MACRO, + // CHAR, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// String + ////------- + //TEST(Parse_A_Macro_Taking_One_String) + //{ + // std::string input("\% foo [ (St) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_String_Parameter) + //{ + // std::string input( + // "\% foo [ (St) : $1 ]\n" + // "foo \"\"" + // ); + // eTokenTypes expected[] = { + // MACRO, + // STRING, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Symbol + ////------- + //TEST(Parse_A_Macro_Taking_One_Symbol) + //{ + // std::string input("\% foo [ (Sy) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Symbol_Parameter) + //{ + // std::string input( + // "\% foo [ (Sy) : $1 ]\n" + // "foo $bar" + // ); + // eTokenTypes expected[] = { + // MACRO, + // SYMBOL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Expression + ////----------- + //TEST(Parse_A_Macro_Taking_One_Expression) + //{ + // std::string input("\% foo [ (E) : $1 ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_A_Expression_Parameter) + //{ + // std::string input( + // "\% foo [ (E) : $1 ]\n" + // "foo 1 + 1" + // ); + // eTokenTypes expected[] = { + // MACRO, + // NUM, NUM, ADD, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //// Corner Cases + ////------------- + //TEST(Throw_Exception_When_Invalid_Macro_Param_Type_Used) + //{ + // std::string input("\% foo [ (Z) : $1 ]"); + // TestParserThrowsException(input); + //} + + //TEST(Throw_Exception_When_No_Macro_Pattern_Matches) + //{ + // std::string input( + // "\% foo [ (I) : $1 ]\n" + // "foo 1.0" //Expecting and ID but a number is given + // ); + // TestParserThrowsException(input); + //} + + //TEST(Parse_A_Macro_With_Multiple_Parameter_Types) + //{ + // std::string input("\% tuple [ (E E) : ($1,$2) ]"); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_Multiple_Parameter_Types) + //{ + // std::string input( + // "\% tuple [ (E E) : ($1,$2) ]\n" + // "tuple 1.0 'a'" + // ); + // eTokenTypes expected[] = { + // MACRO, + // NUM, CHAR, LIST, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Parse_A_Macro_With_Multiple_Patterns) + //{ + // std::string input( + // // Emulate an If statement + // "\% if [\n" + // " (E B B) : exec_if($1,$2,$3),\n" + // " (E B) : exec_if($1,$2)\n" + // "]" + // ); + // eTokenTypes expected[] = { + // MACRO, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Use_A_Macro_With_Multiple_Patterns) + //{ + // std::string input( + // // Emulate an If statement + // "\% if [\n" + // " (E B B) : exec_if($1,$2,$3),\n" + // " (E B) : exec_if($1,$2)\n" + // "]\n" + // "if (1 == 1) {}\n" + // "if (1 == 1) {} {}\n" + // ); + // eTokenTypes expected[] = { + // MACRO, + // ID, NUM, NUM, EQ, PARAMS, BLOCK, FUNC, LIST, FN_CALL, + // ID, NUM, NUM, EQ, PARAMS, BLOCK, FUNC, PARAMS, BLOCK, FUNC, LIST, FN_CALL, + // PROGRAM + // }; + // TestParserWithInput( input, expected ); + //} + + ////------------------------------------------------------------------------- + //// Test General Corner Cases + ////------------------------------------------------------------------------- + //TEST(Parse_An_Empty_Program) + //{ + // std::string input(""); + // eTokenTypes expected[] = { PROGRAM }; + // TestParserWithInput( input, expected ); + //} + + //TEST(Throw_Exception_When_Literal_On_Left_Side_Of_Assignment) + //{ + // std::string input("[] = 5"); + // TestParserThrowsException(input); + //} } -- 2.52.0