| -- @authors Frédéric Jouault |
| -- @date 2007/07/25 |
| -- @description This TCS model defines the syntax of the ACG language. |
| syntax ACG { |
| |
| primitiveTemplate identifier for String default using NAME: |
| value = "%token%"; |
| |
| primitiveTemplate identifierOrKeyword for String using NAME orKeyword: |
| value = "%token%"; |
| |
| primitiveTemplate stringSymbol for String using STRING: |
| value = "ei.unescapeString(%token%, 1)", |
| serializer="'\'' + %value%.toCString() + '\''"; |
| |
| primitiveTemplate integerSymbol for Integer default using INT: |
| value = "Integer.valueOf(%token%)"; |
| |
| template ACG main |
| : "acg" metamodel "startsWith" startsWith "{" [ |
| elements |
| ] "}" |
| ; |
| |
| template ACGElement abstract; |
| |
| template Function |
| : "function" context "::" name |
| "(" (isDefined(parameters) ? parameters{forcedLower = 1, separator = ","} ) ")" "=" |
| body ";" |
| ; |
| |
| template Attribute |
| : "attribute" context "::" name "=" |
| body ";" |
| ; |
| |
| template Parameter addToContext |
| : name |
| ; |
| |
| -- @begin Nodes |
| template Node abstract; |
| |
| template ASMNode context |
| : "asm" element "name" name |
| -- NO mode or guard for ASMNodes: |
| -- (isDefined(mode) ? |
| -- "mode" mode |
| -- ) |
| -- (isDefined(guard) ? "|" guard) |
| "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template CodeNode context |
| : "code" element |
| (isDefined(mode) ? |
| "mode" mode |
| ) |
| (isDefined(guard) ? "|" guard) |
| "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template SimpleNode context |
| : element |
| (isDefined(mode) ? |
| "mode" mode |
| ) |
| (isDefined(guard) ? "|" guard) |
| "{" [ |
| statements |
| ] "}" |
| ; |
| -- @end Nodes |
| |
| -- @begin Statements |
| template Statement abstract; |
| |
| -- @begin CompoundStats |
| template CompoundStat(disambiguate = "(\"if\" LPAREN expression RPAREN LCURLY) | \"foreach\" | \"variable\" | \"operation\" | LSQUARE | \"let\" | \"analyze\"") abstract context; |
| |
| template ForEachStat context |
| : "foreach" "(" iterator "in" collection ")" "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template OnceStat |
| : "[" [ |
| statements |
| ] "]" |
| ; |
| |
| template VariableStat |
| : "variable" definition "named" name "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template OperationStat context |
| : "operation" "context" context "name" name "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template ConditionalStat |
| : "if" "(" condition ")" "{" [ |
| statements |
| ] "}" |
| (isDefined(elseStatements) ? |
| "else" "{" [ |
| elseStatements |
| ] "}" |
| ) |
| ; |
| |
| template LetStat context |
| : "let" variable "=" value "{" [ |
| statements |
| ] "}" |
| ; |
| |
| template AnalyzeStat |
| : "analyze" target |
| (isDefined(mode) ? |
| "mode" mode |
| ) |
| (isDefined(statements) ? |
| "{" [ |
| statements |
| ] "}" |
| ) |
| ; |
| -- @end CompoundStats |
| |
| template ReportStat |
| : "report" severity message |
| ; |
| |
| enumerationTemplate Severity |
| : #critic = "critic", |
| #error = "error", |
| #warning = "warning" |
| ; |
| |
| template FieldStat |
| : "field" name ":" type |
| ; |
| |
| template ParamStat |
| : "param" name ":" type |
| ; |
| |
| -- @begin EmitStats |
| template EmitStat abstract; |
| |
| template LabelStat addToContext |
| : name (isDefined(id) ? "(" id ")") ":" |
| ; |
| |
| template NewStat |
| : "new" |
| ; |
| |
| template NewinStat |
| : "newin" |
| ; |
| |
| template DeleteStat |
| : "delete" |
| ; |
| |
| template DupStat |
| : "dup" |
| ; |
| |
| template DupX1Stat |
| : "dup_x1" |
| ; |
| |
| template PopStat |
| : "pop" |
| ; |
| |
| template SwapStat |
| : "swap" |
| ; |
| |
| template IterateStat |
| : "iterate" |
| ; |
| |
| template EndIterateStat |
| : "enditerate" |
| ; |
| |
| template GetAsmStat |
| : "getasm" |
| ; |
| |
| template FindMEStat |
| : "findme" |
| ; |
| |
| template PushTStat |
| : "pusht" |
| ; |
| |
| template PushFStat |
| : "pushf" |
| ; |
| |
| -- @begin EmitWithOperandStats |
| template EmitWithOperandStat abstract; |
| |
| template PushStat |
| : "push" operand |
| ; |
| |
| template PushIStat |
| : "pushi" operand |
| ; |
| |
| template PushDStat |
| : "pushd" operand |
| ; |
| |
| template LoadStat |
| : "load" operand |
| ; |
| |
| template StoreStat |
| : "store" operand |
| ; |
| |
| template CallStat |
| : "call" operand |
| ; |
| |
| template PCallStat |
| : "pcall" operand |
| ; |
| |
| template SuperCallStat |
| : "supercall" operand |
| ; |
| |
| template GetStat |
| : "get" operand |
| ; |
| |
| template SetStat |
| : "set" operand |
| ; |
| -- @end EmitWithOperandStats |
| |
| -- @begin EmitWithLabelRefStats |
| template EmitWithLabelRefStat abstract; |
| |
| template GotoStat |
| : "goto" label{refersTo = name} |
| ; |
| |
| template IfStat |
| : "if" label{refersTo = name} |
| ; |
| -- @end EmitWithLabelRefStats |
| -- @end EmitStats |
| -- @end Statements |
| |
| template VariableDecl addToContext |
| : name |
| ; |
| |
| -- @begin Expressions |
| template Expression abstract operatored; |
| |
| template VariableExp |
| : variable{refersTo = name} |
| ; |
| |
| template SelfExp |
| : "self" |
| ; |
| |
| template LastExp |
| : "last" |
| ; |
| |
| template IfExp |
| : "if" condition "then" thenExp "else" elseExp "endif" |
| ; |
| |
| operatorTemplate IsAExp(operators = opIsa, source = 'source') |
| : type |
| ; |
| |
| template LetExp context nonPrimary |
| : "let" variable "=" value "in" in |
| ; |
| |
| -- @begin PropertyCallExps |
| operatorTemplate NavigationExp(operators = opPoint, source = 'source') |
| : name{as = identifierOrKeyword} |
| ; |
| |
| operatorTemplate IteratorExp(operators = opRarrow, source = 'source') context |
| : name{as = identifierOrKeyword} "(" iterator "|" body ")" |
| ; |
| |
| operatorTemplate OperationCallExp(operators = opPoint, source = 'source') |
| : name {as = identifierOrKeyword} "(" arguments{separator = ","} ")" |
| ; |
| |
| operatorTemplate OperatorCallExp(operators = |
| opNot opMinus1 |
| opStar opSlash opDiv opMod |
| opPlus opMinus2 |
| opEq opGt opLt opGe opLe opNe |
| opAnd opOr opXor opImplies, |
| source = 'source', storeOpTo = name, storeRightTo = arguments); |
| -- @end PropertyCallExps |
| |
| -- @begin LiteralExps |
| template LiteralExp abstract; |
| |
| template OclUndefinedExp |
| : "OclUndefined" |
| ; |
| |
| -- @begin CollectionExps |
| template CollectionExp abstract; |
| |
| template SequenceExp |
| : "Sequence" "{" elements{separator = ","} "}" |
| ; |
| -- @end CollectionExps |
| |
| -- @begin Primitive LiteralExps |
| template BooleanExp |
| : (value ? "true" : "false") |
| ; |
| |
| template IntegerExp |
| : value |
| ; |
| |
| template StringExp |
| : value{as = stringSymbol} |
| ; |
| -- @end Primitive LiteralExps |
| -- @end LiteralExps |
| -- @end Expressions |
| |
| symbols { |
| lsquare = "["; |
| rsquare = "]" : rightSpace; |
| excl = "!"; |
| coma = "," : leftNone, rightSpace; |
| lparen = "("; |
| rparen = ")" : leftNone, rightSpace; |
| lcurly = "{" : leftSpace; |
| rcurly = "}" : leftNone, rightSpace; |
| semi = ";" : leftNone, rightSpace; |
| colon = ":" : leftSpace, rightSpace; -- except after def where it is leftNone, rightSpace |
| pipe = "|" : leftSpace, rightSpace; |
| sharp = "#" : leftSpace; |
| qmark = "?"; |
| coloncolon = "::" : leftNone, rightNone; |
| |
| -- operator symbols |
| point = "." : leftNone; |
| rarrow = "->" : leftNone; |
| minus = "-" : leftSpace, rightSpace; |
| star = "*" : leftSpace, rightSpace; |
| slash = "/" : leftSpace, rightSpace; |
| plus = "+" : leftSpace, rightSpace; |
| eq = "=" : leftSpace, rightSpace; |
| gt = ">" : leftSpace, rightSpace; |
| lt = "<" : leftSpace, rightSpace; |
| ge = ">=" : leftSpace, rightSpace; |
| le = "<=" : leftSpace, rightSpace; |
| ne = "<>" : leftSpace, rightSpace; |
| larrow = "<-" : leftSpace, rightSpace; |
| } |
| |
| operators { |
| priority 0 { -- 0 is highest |
| opPoint = point, 2; |
| opRarrow = rarrow, 2; |
| } |
| |
| priority 1 { |
| opNot = "not", 1; -- no corresponding symbol => symbol is the keyword defined by the quoted string (which is also the name) |
| opMinus1 = minus, 1; |
| } |
| |
| priority 2 { |
| opStar = star, 2; |
| opSlash = slash, 2; |
| opDiv = "div", 2; |
| opMod = "mod", 2; |
| } |
| |
| priority 3 { |
| opPlus = plus, 2; |
| opMinus2 = minus, 2; |
| } |
| |
| priority 4 { |
| opEq = eq, 2; |
| opGt = gt, 2; |
| opLt = lt, 2; |
| opGe = ge, 2; |
| opLe = le, 2; |
| opNe = ne, 2; |
| opIsa = "isa", 2; |
| } |
| |
| priority 5 { |
| opAnd = "and", 2; |
| opOr = "or", 2; |
| opXor = "xor", 2; |
| opImplies = "implies", 2; |
| } |
| } |
| |
| token COMMENT : endOfLine(start = "--"); |
| |
| lexer = " |
| NL |
| : ( '\\r' '\\n' |
| | '\\n' '\\r' //Improbable |
| | '\\r' |
| | '\\n' |
| ) |
| {newline();} |
| ; |
| |
| WS |
| : ( ' ' |
| | '\\t' |
| ) |
| ; |
| |
| %protected |
| DIGIT |
| : '0'..'9' |
| ; |
| |
| %protected |
| ALPHA |
| : 'a'..'z' |
| | 'A'..'Z' |
| | '_' |
| //For Unicode compatibility (from 0000 to 00ff) |
| | '\\u00C0' .. '\\u00D6' |
| | '\\u00D8' .. '\\u00F6' |
| | '\\u00F8' .. '\\u00FF' |
| ; |
| |
| %protected |
| SNAME |
| %v2 options { |
| %v2 testLiterals = true; |
| %v2 } |
| : (ALPHA) (ALPHA | DIGIT)* |
| ; |
| |
| NAME |
| : ( |
| %v3 SNAME |
| %v2 s:SNAME {if(s.getType() != SNAME) $setType(s.getType());} |
| | '\"' |
| ( ESC |
| | '\\n' {newline();} |
| | ~('\\\\'|'\\\"'|'\\n') |
| )* |
| '\"' |
| %v3 {setText(ei.unescapeString(getText(), 1));} |
| ) |
| ; |
| |
| INT |
| : (DIGIT)+ |
| %v2 (('.' DIGIT)=> '.' (DIGIT)+ {$setType(FLOAT);})? |
| ; |
| |
| %v3 FLOAT : DIGIT+ '.' DIGIT* ; |
| |
| %protected |
| ESC |
| : '\\\\' |
| ( 'n' %v2{%setText(\"\\n\");} |
| | 'r' %v2{%setText(\"\\r\");} |
| | 't' %v2{%setText(\"\\t\");} |
| | 'b' %v2{%setText(\"\\b\");} |
| | 'f' %v2{%setText(\"\\f\");} |
| | '\"' %v2{%setText(\"\\\"\");} |
| | '\\'' %v2{%setText(\"\\'\");} |
| | '\\\\' %v2{%setText(\"\\\\\");} |
| | ( |
| ('0'..'3') |
| ( |
| %v2 options { |
| %v2 warnWhenFollowAmbig = false; |
| %v2 } |
| : ('0'..'7') |
| ( |
| %v2 options { |
| %v2 warnWhenFollowAmbig = false; |
| %v2 } |
| : '0'..'7' |
| )? |
| )? |
| | ('4'..'7') |
| ( |
| %v2 options { |
| %v2 warnWhenFollowAmbig = false; |
| %v2 } |
| : ('0'..'7') |
| )? |
| ) |
| { |
| %v2 String s = %getText; |
| %v2 int i; |
| %v2 int ret = 0; |
| %v2 String ans; |
| %v2 for (i=0; i<s.length(); ++i) |
| %v2 ret = ret*8 + s.charAt(i) - '0'; |
| %v2 ans = String.valueOf((char) ret); |
| %v2 %setText(ans); |
| } |
| ) |
| ; |
| STRING @init {} |
| : (('\\'' (options {greedy = false;} : (('\\\\' ~ '\\n')| '\\n'| ~('\\\\'| '\\n')))* '\\'')) |
| { |
| |
| } |
| |
| ; |
| "; |
| |
| } |