1
0
mirror of https://github.com/twiglet/cs2j.git synced 2025-01-18 13:15:17 +01:00

add precedence table

This commit is contained in:
Kevin Glynn 2010-12-08 13:47:04 +01:00
parent 41c4479473
commit 75ffb63350
5 changed files with 183 additions and 29 deletions

View File

@ -239,7 +239,7 @@ primary_expression:
primary_expression_start: primary_expression_start:
predefined_type predefined_type
| (identifier generic_argument_list) => identifier generic_argument_list | (identifier generic_argument_list) => identifier generic_argument_list
| identifier ((c='::' identifier { Warning($c.line, "[UNSUPPORTED] external aliases are not yet supported"); })?)! | identifier ((c='::'^ identifier { Warning($c.line, "[UNSUPPORTED] external aliases are not yet supported"); })?)!
| 'this' | 'this'
| 'base' | 'base'
| paren_expression | paren_expression
@ -263,7 +263,7 @@ brackets [CommonTree lhs]:
'[' expression_list? ']' -> ^(INDEX { (CommonTree)adaptor.DupTree($lhs) } expression_list?); '[' expression_list? ']' -> ^(INDEX { (CommonTree)adaptor.DupTree($lhs) } expression_list?);
// keving: TODO: drop this. // keving: TODO: drop this.
paren_expression: paren_expression:
'(' expression ')' -> ^(TEMPPARENS expression); '(' expression ')' -> ^(PARENS expression);
arguments [CommonTree lhs]: arguments [CommonTree lhs]:
'(' argument_list? ')' -> ^(APPLY { (CommonTree)adaptor.DupTree($lhs) } argument_list?); '(' argument_list? ')' -> ^(APPLY { (CommonTree)adaptor.DupTree($lhs) } argument_list?);
argument_list: argument_list:
@ -524,7 +524,7 @@ cast_expression:
// //'(' type ')' unary_expression ; // //'(' type ')' unary_expression ;
l='(' type ')' unary_expression -> ^(CAST_EXPR[$l.token, "CAST"] type unary_expression); l='(' type ')' unary_expression -> ^(CAST_EXPR[$l.token, "CAST"] type unary_expression);
assignment_operator: assignment_operator:
'=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>' '>=' ; '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | r='>' '>=' -> RIGHT_SHIFT_ASSIGN[$r.token, ">>="] ;
pre_increment_expression: pre_increment_expression:
s='++' unary_expression -> ^(PREINC[$s.token, "PRE++"] unary_expression) ; s='++' unary_expression -> ^(PREINC[$s.token, "PRE++"] unary_expression) ;
pre_decrement_expression: pre_decrement_expression:
@ -552,7 +552,7 @@ additive_expression:
// >> check needed (no whitespace) // >> check needed (no whitespace)
shift_expression: shift_expression:
(a1=additive_expression -> $a1) ((so='<<' a3=additive_expression -> ^($so $shift_expression $a3)) (a1=additive_expression -> $a1) ((so='<<' a3=additive_expression -> ^($so $shift_expression $a3))
| ('>' '>' a2=additive_expression -> ^(RIGHT_SHIFT $shift_expression $a2)) | (r='>' '>' a2=additive_expression -> ^(RIGHT_SHIFT[$r.token, ">>"] $shift_expression $a2))
)* ; )* ;
relational_expression: relational_expression:
(s1=shift_expression -> $s1) (s1=shift_expression -> $s1)
@ -1138,8 +1138,8 @@ selection_statement:
| switch_statement ; | switch_statement ;
if_statement: if_statement:
// else goes with closest if // else goes with closest if
// i='if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? -> ^(IF[$i.Token] boolean_expression embedded_statement else_statement?) i='if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? -> ^(IF[$i.Token] boolean_expression SEP embedded_statement else_statement?)
'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? // 'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)?
; ;
else_statement: else_statement:
'else' embedded_statement ; 'else' embedded_statement ;

View File

@ -112,9 +112,112 @@ options {
} }
return rets; return rets;
} }
// keving: Found this precedence table on the ANTLR site.
/** Encodes precedence of various operators; indexed by token type.
* If precedence[op1] > precedence[op2] then op1 should happen
* before op2;
* table from http://www.cs.princeton.edu/introcs/11precedence/
*/
private int[] precedence = new int[tokenNames.Length];
private bool precedenceInitted = false;
protected bool IsPrecedenceInitted {
get { return precedenceInitted; }
set { precedenceInitted = value; }
}
private void initPrecedence()
{
if (IsPrecedenceInitted)
return;
for (int i=0; i<precedence.Length; i++) {
// anything but these operators binds super tight
// for example METHOD_CALL binds tighter than PLUS
precedence[i] = int.MaxValue;
}
precedence[ASSIGN] = 1;
precedence[PLUS_ASSIGN] = 1;
precedence[MINUS_ASSIGN] = 1;
precedence[STAR_ASSIGN] = 1;
precedence[DIV_ASSIGN] = 1;
precedence[MOD_ASSIGN] = 1;
precedence[RIGHT_SHIFT_ASSIGN] = 1;
precedence[LEFT_SHIFT_ASSIGN] = 1;
precedence[UNSIGNED_RIGHT_SHIFT_ASSIGN] = 1;
precedence[BIT_AND_ASSIGN] =1;
precedence[BIT_XOR_ASSIGN] = 1;
precedence[BIT_OR_ASSIGN] = 1;
precedence[COND_EXPR] = 2;
precedence[LOG_OR] = 3;
precedence[LOG_AND] = 4;
precedence[BIT_OR] = 5;
precedence[BIT_XOR] = 6;
precedence[BIT_AND] = 7;
precedence[NOT_EQUAL] = 8;
precedence[EQUAL] = 8;
precedence[LTHAN] = 9;
precedence[GT] = 9;
precedence[LTE] = 9;
precedence[GTE] = 9;
precedence[INSTANCEOF] = 9;
precedence[LEFT_SHIFT] = 10;
precedence[RIGHT_SHIFT] = 10;
precedence[UNSIGNED_RIGHT_SHIFT] = 10;
precedence[PLUS] = 11;
precedence[MINUS] = 11;
precedence[DIV] = 12;
precedence[MOD] = 12;
precedence[STAR] = 12;
precedence[CAST_EXPR] = 13;
precedence[NEW] = 13;
precedence[PREINC] = 14;
precedence[PREDEC] = 14;
precedence[MONONOT] = 14;
precedence[MONOTWIDDLE] = 14;
precedence[MONOMINUS] = 14;
precedence[MONOPLUS] = 14;
precedence[POSTINC] = 15;
precedence[POSTDEC] = 15;
precedence[APPLY] = 15;
precedence[INDEX] = 15;
precedence[DOT] = 15;
IsPrecedenceInitted = true;
}
// Compares precedence of op1 and op2.
// Returns -1 if op2 < op1
// 0 if op1 == op2
// 1 if op2 > op1
public int comparePrecedence(IToken op1, IToken op2) {
return Math.Sign(precedence[op2.Type]-precedence[op1.Type]);
}
} }
compilation_unit compilation_unit
@init{
initPrecedence();
// Print all tokens
//for (int i = 0; i < TokenNames.Length; i++) {
// Console.Out.WriteLine("{0} -> {1}", TokenNames[i], i);
//}
}
: :
^(PACKAGE nm=PAYLOAD modifiers? type_declaration[$modifiers.st] { if (IsLast) collectComments(); }) -> ^(PACKAGE nm=PAYLOAD modifiers? type_declaration[$modifiers.st] { if (IsLast) collectComments(); }) ->
package(now = {DateTime.Now}, includeDate = {true}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)}, package(now = {DateTime.Now}, includeDate = {true}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)},
@ -141,10 +244,11 @@ modifier
| m='readonly' | m='volatile' | m='extern' | m='virtual' | m='override' | m=FINAL) | m='readonly' | m='volatile' | m='extern' | m='virtual' | m='override' | m=FINAL)
-> string(payload={$m.text}); -> string(payload={$m.text});
class_member_declaration: class_member_declaration returns [List<String> preComments]:
^(CONST attributes? modifiers? type constant_declarators) ^(CONST attributes? modifiers? type constant_declarators)
| ^(EVENT attributes? modifiers? event_declaration) | ^(EVENT attributes? modifiers? event_declaration)
| ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]? formal_parameter_list? method_body) | ^(METHOD attributes? modifiers? type member_name type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]? formal_parameter_list?
{ $preComments = CollectedComments; } method_body)
-> method(modifiers={$modifiers.st}, type={$type.st}, name={ $member_name.st }, typeparams = { $type_parameter_list.st }, params={ $formal_parameter_list.st }, bodyIsSemi = { $method_body.isSemi }, body={ $method_body.st }) -> method(modifiers={$modifiers.st}, type={$type.st}, name={ $member_name.st }, typeparams = { $type_parameter_list.st }, params={ $formal_parameter_list.st }, bodyIsSemi = { $method_body.isSemi }, body={ $method_body.st })
// | ^(METHOD attributes? modifiers? type method_declaration) -> method(modifiers={$modifiers.st}, type={$type.st}, method={$method_declaration.st}) // | ^(METHOD attributes? modifiers? type method_declaration) -> method(modifiers={$modifiers.st}, type={$type.st}, method={$method_declaration.st})
| ^(INTERFACE attributes? modifiers? interface_declaration[$modifiers.st]) | ^(INTERFACE attributes? modifiers? interface_declaration[$modifiers.st])
@ -238,7 +342,6 @@ primary_expression_start:
| primary_expression_extalias -> unsupported(reason = {"external aliases are not yet supported"}, text= { $primary_expression_extalias.st } ) | primary_expression_extalias -> unsupported(reason = {"external aliases are not yet supported"}, text= { $primary_expression_extalias.st } )
| 'this' | 'this'
| 'base' | 'base'
| ^(TEMPPARENS expression) -> parens(e={$expression.st})
| typeof_expression // typeof(Foo).Name | typeof_expression // typeof(Foo).Name
| literal -> { $literal.st } | literal -> { $literal.st }
; ;
@ -509,6 +612,10 @@ unary_expression:
| ^(PREDEC u6=unary_expression) -> op(op={"--"}, post={$u6.st}) | ^(PREDEC u6=unary_expression) -> op(op={"--"}, post={$u6.st})
| ^(MONOSTAR unary_expression) | ^(MONOSTAR unary_expression)
| ^(ADDRESSOF unary_expression) | ^(ADDRESSOF unary_expression)
// PARENS is not stictly necessary because we insert parens where necessary. However
// we maintin parens inserted by original programmer since tey presumably thought
// it would improve understandability
| ^(PARENS expression) -> parens(e={$expression.st})
; ;
// (cast_expression) => cast_expression // (cast_expression) => cast_expression
@ -678,9 +785,9 @@ class_declaration[StringTemplate modifiersST]
@init { @init {
List<string> preComments = null; List<string> preComments = null;
}: }:
^(c=CLASS { preComments = CollectedComments; } ^(c=CLASS
identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]? identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
class_extends? class_implements? class_body ) class_extends? class_implements? { preComments = CollectedComments; } class_body )
-> class(modifiers = {modifiersST}, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments }, -> class(modifiers = {modifiersST}, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments },
extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}) ; extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}) ;
@ -703,11 +810,8 @@ interface_type_list:
class_body: class_body:
'{' cs+=class_member_declaration_aux* '}' -> class_body(entries={$cs}) ; '{' cs+=class_member_declaration_aux* '}' -> class_body(entries={$cs}) ;
class_member_declaration_aux class_member_declaration_aux:
@init{ member=class_member_declaration -> class_member(comments={ $member.preComments }, member={ $member.st }) ;
List<string> preComments = null;
}:
{ preComments = CollectedComments; } member=class_member_declaration -> class_member(comments={ preComments }, member={ $member.st }) ;
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
@ -1025,10 +1129,10 @@ statement_plus:
; ;
embedded_statement: embedded_statement:
block -> { $block.st } block -> { $block.st }
| selection_statement // if, switch | selection_statement -> { $selection_statement.st } // if, switch
| iteration_statement // while, do, for, foreach | iteration_statement -> { $iteration_statement.st } // while, do, for, foreach
| jump_statement -> { $jump_statement.st } // break, continue, goto, return, throw | jump_statement -> { $jump_statement.st } // break, continue, goto, return, throw
| try_statement | try_statement -> { $try_statement.st }
| checked_statement | checked_statement
| unchecked_statement | unchecked_statement
| lock_statement | lock_statement
@ -1082,14 +1186,14 @@ statement_expression:
expression expression
; ;
selection_statement: selection_statement:
if_statement if_statement -> { $if_statement.st }
| switch_statement ; | switch_statement -> { $switch_statement.st };
if_statement: if_statement:
// else goes with closest if // else goes with closest if
'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? ^(IF boolean_expression SEP embedded_statement else_statement?) -> if(cond= { $boolean_expression.st }, then = { $embedded_statement.st }, else = { $else_statement.st })
; ;
else_statement: else_statement:
'else' embedded_statement ; 'else' embedded_statement -> { $embedded_statement.st } ;
switch_statement: switch_statement:
'switch' '(' expression ')' switch_block ; 'switch' '(' expression ')' switch_block ;
switch_block: switch_block:

View File

@ -108,10 +108,10 @@ primary_expression:
primary_expression_start: primary_expression_start:
predefined_type predefined_type
| (identifier generic_argument_list) => identifier generic_argument_list | (identifier generic_argument_list) => identifier generic_argument_list
| identifier ('::' identifier)? | identifier
| ^('::' identifier identifier)
| 'this' | 'this'
| 'base' | 'base'
| ^(TEMPPARENS expression)
| typeof_expression // typeof(Foo).Name | typeof_expression // typeof(Foo).Name
| literal | literal
; ;
@ -362,6 +362,7 @@ unary_expression:
| ^(PREDEC unary_expression) | ^(PREDEC unary_expression)
| ^(MONOSTAR unary_expression) | ^(MONOSTAR unary_expression)
| ^(ADDRESSOF unary_expression) | ^(ADDRESSOF unary_expression)
| ^(PARENS expression)
; ;
//cast_expression: //cast_expression:
// '(' type ')' non_assignment_expression ; // '(' type ')' non_assignment_expression ;
@ -930,7 +931,8 @@ selection_statement:
| switch_statement ; | switch_statement ;
if_statement: if_statement:
// else goes with closest if // else goes with closest if
'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? // 'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)?
^(IF boolean_expression SEP embedded_statement else_statement?)
; ;
else_statement: else_statement:
'else' embedded_statement ; 'else' embedded_statement ;

View File

@ -32,15 +32,15 @@ tokens {
MONOPLUS; MONOPLUS;
MONOMINUS; MONOMINUS;
MONONOT; MONONOT = '!';
MONOTWIDDLE; MONOTWIDDLE = '~';
MONOSTAR; MONOSTAR;
ADDRESSOF; ADDRESSOF;
PREINC; PREINC;
PREDEC; PREDEC;
POSTINC; POSTINC;
POSTDEC; POSTDEC;
TEMPPARENS; PARENS;
INDEX; INDEX;
APPLY; APPLY;
ARGS; ARGS;
@ -52,10 +52,51 @@ tokens {
NULL_COALESCE='??'; NULL_COALESCE='??';
IF='if'; IF='if';
ASSIGN = '=';
PLUS_ASSIGN = '+=';
MINUS_ASSIGN = '-=';
STAR_ASSIGN = '*=';
DIV_ASSIGN = '/=';
MOD_ASSIGN = '%=';
BIT_AND_ASSIGN = '&=';
BIT_OR_ASSIGN = '|=';
BIT_XOR_ASSIGN = '^=';
LEFT_SHIFT_ASSIGN = '<<=';
RIGHT_SHIFT_ASSIGN;
UNSIGNED_RIGHT_SHIFT_ASSIGN; /* not in C#: >>>= */
COND_EXPR; // (<x> ? <y> : <z>) COND_EXPR; // (<x> ? <y> : <z>)
RIGHT_SHIFT; RIGHT_SHIFT;
INSTANCEOF; INSTANCEOF;
LOG_OR = '||';
LOG_AND = '&&';
BIT_OR = '|';
BIT_XOR = '^';
BIT_AND = '&';
NOT_EQUAL = '!=';
EQUAL = '==';
LTHAN = '<';
LTE = '<=';
GTE = '>=';
LEFT_SHIFT = '<<';
RIGHT_SHIFT;
UNSIGNED_RIGHT_SHIFT; /* not in C#: >>> */
PLUS = '+';
DIV = '/';
MOD = '%';
STAR = '*';
TYPE; TYPE;
ENUM_BODY; ENUM_BODY;
TYPE_PARAM_CONSTRAINT; TYPE_PARAM_CONSTRAINT;

View File

@ -119,6 +119,13 @@ type_parameter_list(items) ::= <<
extends(types) ::= "<if(types)>extends <types; separator=\",\"><endif>" extends(types) ::= "<if(types)>extends <types; separator=\",\"><endif>"
imps(types) ::= "<if(types)>implements <types; separator=\",\"><endif>" imps(types) ::= "<if(types)>implements <types; separator=\",\"><endif>"
// ******* STATEMENTS *******
if(cond,then,else) ::= <<
if (<cond>)
<then>
<else>
>>
// ******* EXPRESSIONS ******* // ******* EXPRESSIONS *******
cast_expr(type, exp) ::= "(<type>)<exp>" cast_expr(type, exp) ::= "(<type>)<exp>"