%{ # include # include "Node.h" extern int yylex(void); extern int yyEOF; # define YYSTYPE oop # define YYDEBUG 0 # if (YYDEBUG) # define note() printf("%s\n", yyrule[yyn]) # else # define note() # endif void yyerror(const char *reason); # if (OOP_USE_GC) # define malloc GC_malloc # define realloc GC_realloc # define free GC_free # endif %} %start Program %token IDENTIFIER BINARY KEYWORD KEYWORDS CHARACTER INTEGER STRING EXTERN ASSIGN ELLIPSIS %% Program : TranslationUnit { $1->compile(); } ; TranslationUnit : /* empty */ { $$= new ProgramNode(); } | TranslationUnit TopLevelExpression { ($$= $1)->add($2); } ; TopLevelExpression : ExecDefinition { $$= $1; } | MethodDefinition { $$= $1; } | ClassDefinition { $$= $1; } ; ExecDefinition : '[' Sequence ']' { $$= ExecNode::withSequence($2); } | EXTERN { $$= ExecNode::withSequence(SequenceNode::withStatement(ExternNode::withCode($1))); } ; ClassDefinition : IDENTIFIER '(' Slots ')' { $$= ClassNode::withNameSlots($1, $3); } | IDENTIFIER ':' IDENTIFIER '(' Slots ')' { $$= ClassNode::withNameSuperSlots($1, $3, $5); } ; Slots : /* empty */ { note(); $$= new ListNode(); } | Slots IDENTIFIER { note(); ($$= $1)->add($2); } | Slots EXTERN { note(); ($$= $1)->add(ExternNode::withCode($2)); } ; MethodDefinition : IDENTIFIER Pattern '[' Sequence ']' { note(); $$= $2->withClassSequence($1, $4); } | IDENTIFIER Pattern EXTERN { note(); $$= $2->withClassSequence($1, SequenceNode::withStatement(ExternNode::withCode($3))); } ; Pattern : UnaryPattern { note(); $$= $1; } | BinaryPattern { note(); $$= $1; } | KeywordPattern { note(); $$= $1; } ; UnaryPattern : IDENTIFIER { note(); $$= MethodNode::withSelector($1); } ; BinaryPattern : BINARY IDENTIFIER { note(); $$= MethodNode::withSelectorArgument($1, $2); } ; KeywordPattern : NamedKeywordPattern { note(); $$= $1; } | NamedKeywordPattern ELLIPSIS { note(); $$= $1->beVariadic(); } ; NamedKeywordPattern : KEYWORD IDENTIFIER { note(); $$= MethodNode::withSelectorArgument($1, $2); } | KeywordPattern KEYWORD IDENTIFIER { note(); $$= $1->addKeywordArgument($2, $3); } ; Sequence : /* empty */ { note(); $$= SequenceNode::empty(); } | Statements { note(); $$= SequenceNode::withStatements($1); } | '|' '|' { note(); $$= SequenceNode::empty(); } | '|' '|' Statements { note(); $$= SequenceNode::withStatements($3); } | '|' Temps '|' { note(); $$= SequenceNode::withTemporaries($2); } | '|' Temps '|' Statements { note(); $$= SequenceNode::withTemporariesStatements($2, $4); } ; Temps : IDENTIFIER { note(); $$= ListNode::with($1); } | Temps IDENTIFIER { note(); ($$= $1)->add($2); } ; Statements : '^' Expression { note(); $$= ListNode::with(ReturnNode::withValue($2)); } | '^' Expression Dots { note(); $$= ListNode::with(ReturnNode::withValue($2)); } | StatementList { note(); $$= $1; } | StatementList Dots { note(); $$= $1; } | StatementList Dots '^' Expression { note(); ($$= $1)->add(ReturnNode::withValue($4)); } | StatementList Dots '^' Expression Dots { note(); ($$= $1)->add(ReturnNode::withValue($4)); } ; StatementList : Expression { note(); $$= ListNode::with($1); } | StatementList Dots Expression { note(); ($$= $1)->add($3); } ; Dots : '.' { note(); } | ELLIPSIS { note(); } | Dots '.' { note(); } ; Expression : Primary { note(); $$= $1; } | IDENTIFIER ASSIGN Expression { note(); $$= AssignmentNode::withVariableValue(VariableNode::withName($1), $3); } | Cascade { note(); $$= $1; } | EXTERN { note(); $$= ExternNode::withCode($1); } ; Cascade : Send { note(); $$= $1; } | Cascade ';' Message { note(); ($$= $1)->addCascade($3); } ; Send : UnarySend { note(); $$= $1; } | BinarySend { note(); $$= $1; } | KeywordSend { note(); $$= $1; } ; UnarySend : Primary UnaryMessage { note(); $$= $2->addReceiver($1); } | UnarySend UnaryMessage { note(); $$= $2->addReceiver($1); } ; BinarySend : Primary BinaryMessage { note(); $$= $2->addReceiver($1); } | UnarySend BinaryMessage { note(); $$= $2->addReceiver($1); } | BinarySend BinaryMessage { note(); $$= $2->addReceiver($1); } ; KeywordSend : Primary KeywordMessage { note(); $$= $2->addReceiver($1); } | UnarySend KeywordMessage { note(); $$= $2->addReceiver($1); } | BinarySend KeywordMessage { note(); $$= $2->addReceiver($1); } ; Message : UnaryMessage { note(); $$= $1; } | BinaryMessage { note(); $$= $1; } | KeywordMessage { note(); $$= $1; } ; UnaryMessage : IDENTIFIER { note(); $$= SendNode::withSelector($1); } ; BinaryMessage : BINARY BinaryArgument { note(); $$= SendNode::withSelectorArgument($1, $2); } ; BinaryArgument : Primary { note(); $$= $1; } | UnarySend { note(); $$= $1; } ; KeywordMessage : NamedKeywordMessage { note(); $$= $1; } | KeywordMessage ':' KeywordArgument { note(); $$= $1->addArgument($3); } ; NamedKeywordMessage : KEYWORD KeywordArgument { note(); $$= SendNode::withSelectorArgument($1, $2); } | NamedKeywordMessage KEYWORD KeywordArgument { note(); $$= $1->addKeywordArgument($2, $3); } ; KeywordArgument : Primary { note(); $$= $1; } | UnarySend { note(); $$= $1; } | BinarySend { note(); $$= $1; } ; Block : '[' Sequence ']' { note(); $$= BlockNode::withSequence($2); } | '[' Parameters '|' Sequence ']' { note(); $$= BlockNode::withArgumentsSequence($2, $4); } ; Parameters : ':' IDENTIFIER { note(); $$= ListNode::with($2); } | Parameters ':' IDENTIFIER { note(); ($$= $1)->add($3); } ; Primary : IDENTIFIER { note(); $$= VariableNode::withName($1); } | Literal { note(); $$= $1; } | Block { note(); $$= $1; } | '(' Expression ')' { note(); $$= $2; } ; Literal : INTEGER { note(); $$= IntegerNode::fromString($1); } | CHARACTER { note(); $$= CharacterNode::fromString($1); } | STRING { note(); $$= StringNode::fromString($1); } | Symbol { note(); $$= $1; } | Array { note(); $$= $1; } ; Symbol : '#' IDENTIFIER { note(); $$= SymbolNode::fromString($2); } | '#' STRING { note(); $$= SymbolNode::fromString($2); } | '#' BINARY { note(); $$= SymbolNode::fromString($2); } | '#' KEYWORD { note(); $$= SymbolNode::fromString($2); } | '#' KEYWORDS { note(); $$= SymbolNode::fromString($2); } ; Array : '#' '[' ArrayBytes ']' { note(); $$= ByteArrayNode::withElements($3); } | '#' '{' ArrayWords '}' { note(); $$= WordArrayNode::withElements($3); } | '#' '(' ArrayLiterals ')' { note(); $$= ArrayNode::withElements($3); } ; ArrayBytes : /* empty */ { note(); $$= ListNode::empty(); } | ArrayBytes INTEGER { note(); ($$= $1)->add(IntegerNode::fromString($2)); } ; ArrayWords : /* empty */ { note(); $$= ListNode::empty(); } | ArrayWords INTEGER { note(); ($$= $1)->add(IntegerNode::fromString($2)); } ; ArrayLiterals : /* empty */ { note(); $$= new ListNode(); } | ArrayLiterals ArrayLiteral { note(); ($$= $1)->add($2); } ; ArrayLiteral : Literal { note(); $$= $1; } | IDENTIFIER { note(); $$= SymbolNode::fromString($1); } | BINARY { note(); $$= SymbolNode::fromString($1); } | KEYWORD { note(); $$= SymbolNode::fromString($1); } | KEYWORDS { note(); $$= SymbolNode::fromString($1); } | '(' ArrayLiterals ')' { note(); $$= ArrayNode::withElements($2); } | '{' ArrayWords '}' { note(); $$= WordArrayNode::withElements($3); } | '[' ArrayBytes ']' { note(); $$= ByteArrayNode::withElements($2); } ; %% #include extern char *yyFile; extern int yyLine; void yyerror(const char *reason) { extern char *yytext; fprintf(stderr, "%s:%d: %s near token '%s'\n", yyFile, yyLine, reason, *yytext ? yytext : ""); exit(1); }