// // Interpreter.ym // GedcomInterpreter // // Created by Thomas Wetmore on 3/10/2010. // Last changed on 10/15/2010. // Copyright 2010 DeadEnds Software. All rights reserved. // %{ #import #import "TWInterpreter.h" #import "TWInterpStatement.h" #import "TWInterpExpression.h" #import "TWInterpModule.h" #import "TWInterpLexer.h" #import "TWInterpParameter.h" #import "TWInterpInitializer.h" // All semantic values are Objective-C objects. #define YYSTYPE id // The interface between the the yacc-generated parser and the lexer is these global variables. extern TWInterpLexer* globalLexer; extern NSMutableArray* globalModules; extern NSMutableArray* globalDeclarations; extern NSMutableArray* globalIncludes; extern void yyerror (char* message); extern int yylex (); %} %token TYPE // Boolean, Character, Integer, Float, List, Set, Table, Node, Record %right ASGNOP // = %left OROP // || %left ANDOP // && %left EQOP // ==, != %left RELOP // <, <=, >, >= %left ADDOP // +, - %left MULOP // *, /, % %right UNARYOP // +, -, ! %right NOTOP // ! %left DOTOP // . %token IDEN // Identifier -- value is an autoreleased NSString*. %token TRUECONS FALSECONS // Boolean constants -- autoreleased NSNumber*s with a boolean. %token CCONS // Character constant -- autoreleased NSNumber* with unsigned short, I think. %token ICONS // Integer constant -- autoreleased NSNumber* with an int. %token FCONS // Float constant -- autoreleased NSNumber* with a double. %token SCONS // String constant -- autoreleased NSString* without quotes. %token WHILE DO FOR IN IF ELSE %token BREAK CONTINUE RETURN %token FORNODES %token INCLUDE %% definitions : definition | definitions definition ; definition : declaration { // Global declaration. [globalDeclarations addObject: $1]; } | module { // Top level procedure or function. [globalModules addObject: $1]; } | INCLUDE SCONS ';' { // Include lines allow one program file to depend on others. [globalIncludes addObject: $2]; } ; declaration : TYPE m identifiers ';' { // Semantic value is a declaration statement. $$ = [[TWInterpDeclaration alloc] initWithType: $1 initializers: $3]; [$$ setLineNumber: $2]; } ; module : TYPE m IDEN '(' parameterso ')' block { // Semantic value is a module object. $$ = [[TWInterpModule alloc] initWithType: $1 name: $3 parameters: $5 block: $7]; [$$ setLineNumber: $2]; } ; identifiers : IDEN initializero { $$ = [[NSMutableArray alloc] initWithObjects: [[TWInterpInitializer alloc] initWithName: $1 initialExpressions: $2], nil]; } | identifiers ',' IDEN initializero { $$ = $1; [$$ addObject: [[TWInterpInitializer alloc] initWithName: $3 initialExpressions: $4]]; } ; initializero: initializer { // Value is an array of expression (usually of count 1) or nil. $$ = $1; } | /* empty */ { $$ = nil; } ; initializer : ASGNOP initialvalue { // Value is an array of expressions (usually of count 1). $$ = $2; } ; initialvalue: expression { // Value is an array of expressions (usually of count 1). $$ = [[NSArray alloc] initWithObjects: $1, nil]; [$1 release]; } | '{' expressionso '}' { $$ = $2; } ; parameterso : parameters { // Semantic value is an array of parameter objects. $$ = $1; } | /* empty */ { $$ = nil; } ; parameters : parameter { // Semantic value is an array of parameter objects. $$ = [[NSMutableArray alloc] initWithObjects: $1, nil]; } | parameters ',' parameter { $$ = $1; [$$ addObject: $3]; } ; parameter : TYPE IDEN { // Semantic value is a parameter object. $$ = [[TWInterpParameter alloc] initWithType: $1 name: $2]; } ; statementso : statements { // Semantic value is an array of statement objects. $$ = $1; } | /* empty */ { $$ = nil; } ; statements : statement { // Semantic value is an array of statement objects. $$ = [[NSMutableArray alloc] initWithObjects: $1, nil]; } | statements statement { $$ = $1; [$$ addObject: $2]; } ; statement : expression m ';' { // Semantic value is statement subclass object. $$ = [[TWInterpExpressionStatement alloc] initWithExpression: $1]; [$$ setLineNumber: $2]; } | declaration { $$ = $1; } | IF m '(' expression ')' statement { $$ = [[TWInterpIfStatement alloc] initWithConditional: $4 thenStatement: $6 elseStatement: nil]; [$$ setLineNumber: $2]; } | IF m '(' expression ')' statement ELSE statement { $$ = [[TWInterpIfStatement alloc] initWithConditional: $4 thenStatement: $6 elseStatement: $8]; [$$ setLineNumber: $2]; } | WHILE m '(' expression ')' statement { $$ = [[TWInterpWhileStatement alloc] initWithConditional: $4 statement: $6]; [$$ setLineNumber: $2]; } | DO m statement WHILE '(' expression ')' ';' { $$ = [[TWInterpDoStatement alloc] initWithStatement: $3 conditional: $6]; [$$ setLineNumber: $2]; } | block { $$ = $1; } | RETURN m expressiono ';' { $$ = [[TWInterpReturnStatement alloc] initWithExpression: $3]; [$$ setLineNumber: $2]; } | CONTINUE m ';' { $$ = [[TWInterpContinueStatement alloc] init]; [$$ setLineNumber: $2]; } | BREAK m ';' { $$ = [[TWInterpBreakStatement alloc] init]; [$$ setLineNumber: $2]; } | FOR m '(' expressiono ';' expressiono ';' expressiono ')' statement { $$ = [[TWInterpForStatement alloc] initWithInitializer: $4 conditional: $6 incrementer: $8 statement: $10]; [$$ setLineNumber: $2]; } | FOR m '(' TYPE IDEN IN expression ')' statement { $$ = [[TWInterpEnumerateStatement alloc] initWithType: $4 iterator: $5 collection: $7 statement: $9]; [$$ setLineNumber: $2]; } | FORNODES m '(' expression ',' IDEN ')' statement { $$ = [[TWInterpForNodesStatement alloc] initWithExpression: $4 iterator: $6 statement: $8]; [$$ setLineNumber: $2]; } ; block : '{' m statementso '}' { $$ = [[TWInterpBlockStatement alloc] initWithStatements: $3]; [$$ setLineNumber: $2]; } ; expression : IDEN m { // Semantic value is a variable object. $$ = [[TWInterpVariable alloc] initWithName: $1]; [$$ setLineNumber: $2]; } | ICONS m { // Semantic value is an integer constant object. $$ = [[TWInterpIntegerConstant alloc] initWithNumber: $1]; [$$ setLineNumber: $2]; } | FCONS m { $$ = [[TWInterpFloatConstant alloc] initWithNumber: $1]; [$$ setLineNumber: $2]; } | SCONS m { // Semantic value is a string constant object. $$ = [[TWInterpStringConstant alloc] initWithString: $1]; [$$ setLineNumber: $2]; } | boolconstant m { // Semantic value is a number with a boolean value. $$ = $1; [$$ setLineNumber: $2]; } | '(' expression ')' { $$ = $2; } | IDEN m '(' expressionso ')' { // Semantic value is a call expression. $$ = [[TWInterpCallExpression alloc] initWithName: $1 arguments: $4]; [$$ setLineNumber: $2]; } | expression ADDOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression MULOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression RELOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression EQOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression ANDOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression OROP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression ASGNOP m expression { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | expression DOTOP m member { // Semantic value is a binary expression. $$ = [[TWInterpBinaryExpression alloc] initLeft: $1 right: $4 operator: $2]; [$$ setLineNumber: $3]; } | ADDOP m expression %prec UNARYOP { // Semantic value is a unary expression. $$ = [[TWInterpUnaryExpression alloc] initExpression: $3 operator: $1]; [$$ setLineNumber: $2]; } | NOTOP m expression { // Semantic value is a unary expression. $$ = [[TWInterpUnaryExpression alloc] initExpression: $3 operator: $1]; [$$ setLineNumber: $2]; } ; member : IDEN m { $$ = [[TWInterpCallExpression alloc] initWithName: $1 arguments: nil]; [$$ setLineNumber: $2]; } | IDEN m '(' expressionso ')' { $$ = [[TWInterpCallExpression alloc] initWithName: $1 arguments: $4]; [$$ setLineNumber: $2]; } ; expressiono : expression { $$ = $1; } | /* empty */ { $$ = nil; } ; expressionso: expressions { $$ = $1; } | /* empty */ { $$ = nil; } ; expressions : expression { $$ = [[NSMutableArray alloc] initWithObjects: $1, nil]; } | expressions ',' expression { $$ = $1; [$$ addObject: $3]; } ; boolconstant : TRUECONS { $$ = [[TWInterpBooleanConstant alloc] initWithNumber: [NSNumber numberWithBool: YES]]; } | FALSECONS { $$ = [[TWInterpBooleanConstant alloc] initWithNumber: [NSNumber numberWithBool: NO]]; } ; m : /* empty */ { // Semantic value is the current line number. $$ = [NSNumber numberWithInt: globalLexer.lineNumber]; } ; %%