%{ public class PdlrClass { string name, base_type; List interfaces; List members; public PdlrClass (string name, string baseType, List interfaces, List members) { this.name = name; this.base_type = baseType; this.interfaces = interfaces; this.members = members; } } public abstract class PdlrMember { } %} %token IDENTIFIER %token NUMERIC_LITERAL %token STRING_LITERAL %token CLASS "class" %token EXTENDS "extends" %token IMPLEMENTS "implements" %token WHILE "while" %token BREAK "break" %token RETURN "return" %token IF "if" %token ELSE "else" %token FOR "for" %token SWITCH "switch" %token CASE "case" %token DEFAULT "default" %token NEW "new" %token TRUE "true" %token FALSE "false" %token THIS "this" %token SUPER "super" %token NULL "null" %token PLUS "+" %token MINUS "-" %token ASTERISK "*" %token SLASH "/" %token PERCENT "%" %token PLUS_EQUAL "+=" %token MINUS_EQUAL "-=" %token PLUS_PLUS "++" %token MINUS_MINUS "--" %token EQUAL "=" %token EQUAL2 "==" %token COMMA "," %token DOT "." %token COLON ":" %token SEMICOLON ";" %token QUESTION "?" %token EXCLAIM "!" %token EXCLAIM_EQUAL "!=" %token AND "&" %token AND2 "&&" %token BAR "|" %token BAR2 "||" %token OPEN_CURLY "{" %token CLOSE_CURLY "}" %token OPEN_PAREN "(" %token CLOSE_PAREN ")" %token OPEN_BRACE "[" %token CLOSE_BRACE "]" %token OPEN_ANGLE "<" %token OPEN_ANGLE2 "<<" %token OPEN_ANGLE_EQUAL "<=" %token CLOSE_ANGLE ">" %token CLOSE_ANGLE2 ">>" %token CLOSE_ANGLE_EQUAL ">=" %start top_level_contents %% identifier : IDENTIFIER top_level_contents : // empty { return new List (); } | top_level_content top_level_contents { var l = (List) $2; l.Insert (0, $1); $$ = l; } ; top_level_content : statements | callable_expression | class_declaration | global_function_definition ; global_function_definition : function_definition ; class_declaration : CLASS identifier opt_derivation_indication opt_implementation_indications OPEN_CURLY class_member_definitions CLOSE_CURLY { var name = (string) $2; var baseType = (string) $3; var interfaces = (List) $4; var members = (List) $5; $$ = new PdlrClass (name, baseType, interfaces, members); } opt_derivation_indication : { $$ = null; } // empty | derivation_indication ; opt_implementation_indications : { $$ = null; } // empty | implementation_indications ; derivation_indication : EXTENDS identifier { $$ = $2; } ; implementation_indications : IMPLEMENTS identifier_list_comma { $$ = $2; } identifier_list_comma : identifier { var l = new List (); l.Add ($1); $$ = l; } | identifier COMMA identifier_list_comma { var l = (List) $3; l.Insert (0, (string) $1); $$ = l; } ; class_member_definitions : { $$ = null; } // empty | class_member_definition class_member_definitions { var l = (List) $2 ?? new List (); l.Insert (0, (PdlrMember) $1); $$ = l; } class_member_definition : field_definition | constructor_definition | function_definition field_definition : variable_declaration_statement SEMICOLON { $$ = $1; } constructor_definition : function_definition_base { $$ = new PdlrConstructor ((FunctionBase) $1); } function_definition : type_name function_definition_base { $$ = new PdlrFunction ((string) $1, (FunctionBase) $2); } function_definition_base : identifier OPEN_PAREN argument_definitions CLOSE_PAREN statement_block { $$ = new FunctionBase ((string) $1, (List) $3, (List) $5); } argument_definitions : { $$ = null; } // empty | argument_definition COMMA argument_definitions { var l = (List) $3 ?? new List (); l.Insert (0, (FunctionArgument) $1); $$ = l; } argument_definition : type_name identifier { $$ = new FunctionArgument ((string) $1, (string) $2); } // Statements statement_block : OPEN_CURLY statements CLOSE_CURLY { $$ = $2; } statements : { $$ = null; } // empty | statement statements { var l = (List) $2 ?? new List (); l.Insert (0, (Expression) $1); $$ = l; } statement : statement_with_semicolon SEMICOLON { $$ = $1; } | statement_without_semicolon statement_with_semicolon : return_statement | abstract_assignment_statement | break_statement | increment_statement | decrement_statement | variable_declaration_statement | call_super_statement statement_without_semicolon : if_statement | for_statement | while_statement | switch_statement abstract_assignment_statement : assignment_statement | add_assignment_statement | subtract_assignment_statement add_assignment_statement : expression PLUS_EQUAL expression { var e1 = (Expression) $1, e2 = (Expression) $3; $$ = Expression.Assign (e1, Expression.AddChecked (e1, e2)); } subtract_assignment_statement : expression MINUS_EQUAL expression { var e1 = (Expression) $1, e2 = (Expression) $3; $$ = Expression.Assign (e1, Expression.SubtractChecked (e1, e2)); } increment_statement : expression PLUS_PLUS // FIXME: no pre-positioned increment? { var e1 = (Expression) $1; $$ = Expression.Assign (e1, Expression.AddChecked (e1, Expression.Constant (1))); } decrement_statement : expression MINUS_MINUS // FIXME: no pre-positioned increment? { var e1 = (Expression) $1; $$ = Expression.Assign (e1, Expression.SubtractChecked (e1, Expression.Constant (1))); } call_super_statement : SUPER OPEN_PAREN function_args CLOSE_PAREN { // FIXME: get current type, find base constructor, and call it. } return_statement : RETURN expression { $$ = Expression.Return ((Expression) $2); } assignment_statement : variable_or_member_reference EQUAL expression { $$ = Expression.Assign ((Expression) $1, (Expression) $2); } while_statement : WHILE OPEN_PAREN expression CLOSE_PAREN statement_block { $$ = Expression.Loop ((Expression) $3, null, Expression.Block (null, (List) $5), Expression.Break (null), null); } break_statement : BREAK { $$ = Expression.Break (null); } /// variable-declaration variable_declaration_statement : type_name opt_array_indicator variable_declaration_pairs SEMICOLON { // FIXME: CreateType() is not likely possible here. var l = new List (); Type t = CreateType ((string) $1, (bool) $2); foreach (VariableDeclarationPair p in $3) l.Add (Expression.Variable (t, } type_name : identifier opt_array_indicator : { $$ = false; } // empty | OPEN_BRACE CLOSE_BRACE { $$ = true; } variable_declaration_pairs : variable_declaration_pair { var l = new List (); l.Add ((VariableDeclarationPair) $1); $$ = l; } | variable_declaration_pair COMMA variable_declaration_pairs { var l = (List) $3; l.Insert (0, (VariableDeclarationPair) $1); $$ = l; } variable_declaration_pair : identifier opt_variable_initializer { $$ = new VariableDeclarationPair ((string) $1, (Expression) $2); } opt_variable_initializer : { $$ = null; } // empty | variable_initializer variable_initializer : EQUAL expression { $$ = $2; } /// if-else if_statement : IF OPEN_PAREN expression CLOSE_PAREN statement_block opt_else_block { var cond = (Expression) $3; var tb = (List) $5; var fb = (List) $6; $$ = eb != null ? Expression.IfThenElse (cond, Expression.Block (tb), Expression.Block (fb)) : Expression.IfThen (cond, Expression.Block (tb)); } opt_else_block : { $$ = null; } // empty | else_block else_block : ELSE statement_block { $$ = $2; } /// for for_statement : FOR OPEN_PAREN for_initializer SEMICOLON expression SEMICOLON for_continuations CLOSE_PAREN statement_block { var init = (List) $3; var cond = (Expression) $5; var cont = (List) $7; var loop = Expression.Loop (cond, cont != null ? Expression.Block (cont) : null, Expression.Block ((List) $9), Expression.Break (null), new LabelTarget (null)); $$ = init != null ? Expression.Block (init, loop) : loop; } for_initializer : { $$ = null; } // empty | variable_declaration_statement | abstract_assignment_list abstract_assignment_list : abstract_assignment_statement { var l = new List (); l.Add ((Expression) $1); $$ = l; } | abstract_assignment_statement COMMA abstract_assignment_list { var l = (List) $3; l.Insert (0, (Expression) $1); $$ = l; } for_continuations : statements // FIXME: no constraints? /// switch-case switch_statement : SWITCH OPEN_PAREN expression CLOSE_PAREN OPEN_CURLY switch_case_list CLOSE_CURLY { $$ = Expression.Switch (null, null, (Expression) $3, ((List) $6).ToArray ()); } switch_case_list : { $$ = new List (); } // empty | switch_case_default switch_case_list // switch_default cannot appear twice { var l = (List) $2; l.Insert (0, (SwitchCase) $1); $$ = l; } switch_case_default : switch_case | switch_default switch_case : CASE literal COLON statements { var l = (List) $4; // must end with break_statement if (!(l [l.Length - 1] is BreakExpression)) l.Add (Expression.Break (null)); $$ = Expression.SwitchCase (GetIntValue ((ConstantExpression) $2), Expression.Block (l)); } switch_default : DEFAULT COLON statements { var l = (List) $3; // must end with break_statement if (!(l [l.Length - 1] is BreakExpression)) l.Add (Expression.Break (null)); $$ = Expression.DefaultCase (Expression.Block (l)); } // Expressions expression : callable_expression | operation_expression | variable_or_member_reference | literal | field_access_expression | super_expression | this_expression | new_expression | array_access_expression | null_expression | parenthesized_expression | numeric_negation_expression variable_or_member_reference : identifier { // FIXME: how can I distinguish variable and field-or-property? // FIXME: how can I instantiate an Expression for varref? } // new new_expression : new_object_expression | new_array_expression new_object_expression : NEW function_call_base { // FIXME: CreateType() is unlikely possible var fcb = KeyValuePair> $2; // FIXME: no CallSiteBinder? $$ = Expression.New (CreateType (fcb.Key), null, fcb.Value); } new_array_expression : NEW identifier OPEN_BRACE expression CLOSE_BRACE { // FIXME: CreateType() is unlikely possible $$ = Expression.NewArrayBounds (CreateType ((string) $2), (Expression) $4); } // callable expressions callable_expression : function_call_expression | function_access_expression function_call_expression : function_call_base function_call_base : identifier OPEN_PAREN function_args CLOSE_PAREN { $$ = new KeyValuePair> ((string) $1, (List) $3); } function_args : { $$ = new List (); } // empty | function_arg_list function_arg_list : expression { var l = new List (); l.Add ((Expression) $1); $$ = l; } | expression COMMA function_arg_list { var l = (List) $3; l.Insert (0, (Expression) $1); $$ = l; } literal : string_literal | numeric_literal | true_expression | false_expression true_expression := TRUE { $$ = Expression.TRue (); } false_expression : FALSE { $$ = Expression.False (); } numeric_literal : NUMERIC_LITERAL string_literal : STRING_LITERAL /// operation expressions operation_expression : comparison_expression | logical_operation_expression | arithmetic_expression comparison_expression : less_than_expression | less_eq_expression | greater_than_expression | greater_eq_expression | eq_expression | not_eq_expression | conditional_expression logical_operation_expression : logical_or_expression | logical_and_expression | logical_not_expression arithmetic_expression : additive_expression | multiplicative_expression additive_expression : add_expression | subtract_expression | bitwise_and_expression | bitwise_or_expression | left_shift_expression | right_shift_expression multiplicative_expression : multiply_expression | divide_expression | modulo_expression // FIXME: "expression" in below items need to be more specific. // For example, First expression in "additive_expression" is // "multiplicative_expression" (for operator priority) field_access_expression : expression DOT identifier { $$ = Expression.PropertyOrField ((Expression) $1, (string) $3); } function_access_expression : expression DOT function_call_base { var inst = (Expression) $1; var fcb = (KeyValuePair>) $3; // FIXME: GetMethod() is unlikely possible $$ = Expression.Call (inst, GetMethod (inst, fcb.Key), fcb.Value.ToArray ()); } super_expression : SUPER { // FIXME: needs current type context, Type, and then base type } this_expression := THIS { } // FIXME: how can I represent it? array_access_expression : expression OPEN_BRACE expression CLOSE_BRACE { $$ = Expression.ArrayIndex ((Expression) $1, (Expression) $3); } null_expression : NULL { $$ = Expression.Null (); } parenthesized_expression : OPEN_PAREN expression CLOSE_PAREN { $$ = $2; } less_than_expression : expression OPEN_ANGLE expression { $$ = Expression.LessThan ((Expression) $1, (Expression) $3); } less_eq_expression : expression OPEN_ANGLE_EQUAL expression { $$ = Expression.LessThanOrEqual ((Expression) $1, (Expression) $3); } greater_than_expression : expression CLOSE_ANGLE expression { $$ = Expression.GreaterThan ((Expression) $1, (Expression) $3); } greater_eq_expression : expression CLOSE_ANGLE_EQUAL expression { $$ = Expression.GreaterThanOrEqual ((Expression) $1, (Expression) $3); } eq_expression : expression EQUAL2 expression { $$ = Expression.Equal ((Expression) $1, (Expression) $3); } not_eq_expression : expression EXCLAIM_EQUAL expression { $$ = Expression.NotEqual ((Expression) $1, (Expression) $3); } conditional_expression : expression QUESTION expression COLON expression { $$ = Expression.Condition ((Expression) $1, (Expression) $3, (Expression) $5); } logical_or_expression : expression BAR2 expression { $$ = Expression.OrElse ((Expression) $1, (Expression) $3); } logical_and_expression : expression AND2 expression { $$ = Expression.AndAlso ((Expression) $1, (Expression) $3); } logical_not_expression : EXCLAIM expression { $$ = Expression.Not ((Expression) $1); } add_expression : expression PLUS expression { $$ = Expression.AddChecked ((Expression) $1, (Expression) $3); } subtract_expression : expression MINUS expression { $$ = Expression.SubtractChecked ((Expression) $1, (Expression) $3); } numeric_negation_expression : MINUS expression { $$ = Expression.MultiplyChecked ((Expression) $1, Expression.Constant (-1)); } multiply_expression : expression ASTERISK expression { $$ = Expression.MultiplyChecked ((Expression) $1, (Expression) $3); } divide_expression : expression SLASH expression { $$ = Expression.DivideChecked ((Expression) $1, (Expression) $3); } modulo_expression : expression PERCENT expression { $$ = Expression.Modulo Checked ((Expression) $1, (Expression) $3); } bitwise_and_expression : expression AND expression { $$ = Expression.And ((Expression) $1, (Expression) $3); } bitwise_or_expression : expression BAR expression { $$ = Expression.Or ((Expression) $1, (Expression) $3); } left_shift_expression : expression OPEN_ANGLE2 expression { $$ = Expression.LeftShift ((Expression) $1, (Expression) $3); } right_shift_expression : expression CLOSE_ANGLE2 expression { $$ = Expression.RightShift ((Expression) $1, (Expression) $3); }