header { } options { language = "CSharp"; namespace = "Ob51.Parsing"; } /*************************** LEXICAL ANALISYS ***************************/ class Ob51Lexer extends Lexer; options { k = 2; caseSensitive = true; testLiterals = false; charVocabulary = '\u0001'..'\uFFFD'; } /* Extra tokens not defined by ANTLR lexer rules but used in syntax */ tokens { BOOLEAN; SHORTCHAR; CHAR; BYTE; SHORTINT; INTEGER; LONGINT; SHORTREAL; REAL; SET; MODULEID; } /* Extra code in the lexer class */ { interface IModuleIDChecker { bool IsModuleID(string id); } IModuleIDChecker ModuleIDChecker = null; bool IsModuleID(string id) { if (ModuleIDChecker != null) { return ModuleIDChecker.IsModuleID(id); } else { return false; } } } WS: ( '\t' | ' ' | '\r' | ('\n' | '\f' | '\u0085' | '\u2028' | '\u2029') { newline(); } )+ { $setType(Token.SKIP); }; protected COMMENTTEXT: ( options { greedy=true; } : ~('(' | '*' | '\n' | '\f' | '\u0085' | '\u2028' | '\u2029') | ('\n' | '\f' | '\u0085' | '\u2028' | '\u2029') { newline(); } | { LA(2) != ')' }? '*' | { LA(2) != '*' }? '(' )*; COMMENT: "(*" COMMENTTEXT (COMMENT COMMENTTEXT)* "*)" { $setType(Token.SKIP); }; protected DIGIT: '0'..'9'; protected HEXDIGIT: 'A'..'F' | DIGIT; protected LETTER: 'a'..'z' | 'A'..'Z'; ID options { testLiterals = true; } : (LETTER | '_') (LETTER | DIGIT | '_')* { if (IsModuleID($getText)) $setType(MODULEID); }; protected INTEGER: (DIGIT (HEXDIGIT)* ('H' | 'L') ) => DIGIT (HEXDIGIT)* ('H' {$setToken(NumericToken.MakeHexInt($getText));} | 'L' {$setToken(NumericToken.MakeHexLong($getText));} ) | (DIGIT)+ {$setToken(NumericToken.MakeInt($getText));}; protected REAL: (DIGIT)+ '.' (DIGIT)* (SCALEFACTOR)?; protected SCALEFACTOR: 'E' ('+' | '-')(DIGIT)+; protected CHAR : DIGIT (HEXDIGIT)* 'X'; NUM_VALUE: ((DIGIT)+ '.') => REAL {$setToken(NumericToken.MakeReal($getText));} | ( (DIGIT) (HEXDIGIT)* 'X' ) => CHAR {$setToken(NumericToken.MakeChar($getText));} | INTEGER ; STRING: '"' (~'"')* '"' | '\'' (~'\'')* '\''; PUNCTUATION options { testLiterals = true; } : ';' | '.' | ':' | ',' | ":=" | '^' | '|' | '$' | '+' | '-' | '*' | '/' | '&' | '~' | '=' | '#' | '<' | '>' | "<=" | ">=" | ".." | '(' | ')' | '[' | ']' | '{' | '}'; /*************************** SYNTAX ANALISYS ***************************/ class Ob51Parser extends Parser; options { k = 2; } /* Module heading and imports*/ module [out Module module] { ImportList importList_; DeclSeq declsSeq_; StatSeq beginSeq_, endSeq_; }: "MODULE" id_:ID ";" (importList[out _importList])? declsSeq[out _declsSeq] ("BEGIN" statementsSeq[out _beginSeq])? ("CLOSE" statementsSeq[out _endSeq])? {module = new Module(new ID(id_.GetText()), _importList, _declsSeq, _beginSeq, _endSeq);} "END" ID "." EOF; importList[out ImportList importList] { importList = new ImportList(); string nick_ = null, name_; } : "IMPORT" ( ( id1_:ID ":=" {nick = id1_.GetText();})? id2_:ID {name = id2_.GetText();} {importList.AddItem(name_, nick_);} )+ ";" ; /* Declarations */ identDef[out IdentDef identDef]: ID ["*" | "-"]; qualID[out Qualident qualident]: MODULEID "." ID | ID; declsSeq[out DeclSeq declsSeq] { declsSeq = new DeclSeq(); }: ( {ConstDecl constDecl_; }"CONST" ( constDecl[out constDecl_] {declsSeq.AddItem(constDecl); } )* | {TypeDecl typeDecl_;} "TYPE" ( typeDecl[out typeDecl_] {declsSeq.AddItem(typeDecl_); } )* | {VarDecl varDecl_;} "VAR" ( varDecl[out varDecl_] {declsSeq.AddItem(varDecl_);} )* )* ( procDecl | forwardDecl )*; constDecl[out ConstDecl constDecl] { Expression expr_; IdentDef identDef_; }: identDef[out identDef_] "=" constExpr[out expr_] {constDecl = new ConstDecl(identDef_, expr_); }; typeDecl[out TypeDecl typeDecl] { Type type_; IdentDef identDef_; }: identDef[out identDef_] "=" type[out type_] {typeDecl = new TypeDecl(identDef_, type_); }; varDecl[out VarDecl varDecl] { IdentList identList_; Type type_; }: identList[out identList_] ":" type[out type_] {varDecl = new VarDecl(identList_, type_); }; identList[out IdentList identList] { identList = new IdentList(); IdentDef identDef_; }: identDef[out identDef_] /*("AT" constExpr ":" constExpr)? // неясно, что это значит*/ { identList.Add(identDef_); } {identList.Add()} ( "," identDef[out identDef_] /*("AT" constExpr ":" constExpr)?*/ {identList.Add(identdef_); } )*; procDecl[out ProcDecl procDecl]: "PROCEDURE" (receiver)? newID (formalPars)? methAttributes (";" declsSeq "BEGIN" statementsSeq)? "END" ID; forwardDecl[out ForwardDecl forwardDecl]: "PROCEDURE" "^" (receiver)? newID (formalPars)? methAttributes; formalPars[out FormalPars formalPars]: "(" fpSection (";" fpSection)* ")" (":" type)?; fpSection[out FPSection fpSection]: ("VAR" | "IN" | "OUT") ID ("," ID)* ":" type; receiver[out Receiver receiver]: "(" ("VAR" | "IN") ID ":" ID ")"; methAttributes[out MethAttributes methAttributes]: ("," "NEW")? ("," "ABSTRACT" | "EMPTY" | "EXTENSIBLE")? ("," "HANDLER" "OF" constExpr)?; type[out Type type]: qualID | "ARRAY" (constExpr ("," constExpr)*)? "OF" type | ("ABSTRACT" | "EXTENSIBLE" | "LIMITED")? "RECORD" ("(" qualID ")")? fieldsDef (";" fieldsDef)? "END" | "POINTER" "TO" type | "PROCEDURE" (formalParams)?; fieldsDef: newID ("," newID)* ":" type; /* Statements */ statementsSeq: statement (";" statement)*; statement: designator (":=" expr | "(" exprsList ")") | "IF" expr "THEN" statementsSeq ("ELSIF" expr "THEN" statementsSeq)* ("ELSE" statementsSeq)? "END" | "CASE" expr "OF" caseVariant ("|" caseVariant)* ("ELSE" statementsSeq)? "END" | "WHILE" expr "DO" statementsSeq "END" | "REPEAT" statementsSeq "UNTIL" expr | "FOR" ("VAR" ID ":" TYPE | ID) ":=" expr "TO" expr ("BY" constExpr)? "DO" statementsSeq "END" | "LOOP" statementsSeq "END" | "WITH" (guard "DO" statementsSeq)? ("|" guard "DO" statementsSeq)* ("ELSE" statementsSeq)? "END" | "EXIT" | "RETURN" expr; caseVariant: caseLabel ("," caseLabel)* ":" statementsSeq; caseLabel: constExpr (".." constExpr)?; /* Expressions */ constExpr: expr; guard: qualID ":" qualID; expr: simpleExpr (relation simpleExpr)?; relation: "=" | "#" | "<" | "<=" | ">" | ">=" | "IN" | "IS"; simpleExpr: "+" unaryArgument | "-" unaryArgument | unaryArgument; unaryArgument: term (addOp term)*; addOp: "+" | "-" | "OR"; term: factor (mulOp factor)*; mulOp: "*" | "/" | "DIV" | "MOD" | "&"; factor: designator | NUMBER | CHARACTER | STRING | "NIL" | set | "(" expr ")" | "~" factor; set: "{" (setElement ("," setElement)*)? "}"; setElement: expr (".." expr)?; designator: qualID ( options { greedy = true; } : /* options needed to disambiguate designator and "(" */ "." ID | "[" exprsList "]" | "^" | "(" exprsList ")" /* qualID should be an alternative to exprList, but it conflicts */ )* ("$")?; exprsList: expr ("," expr)*;