📄 tinybasic.g
字号:
header{ package tinybasic; import java.util.*;}class TinyBasicParser extends Parser;options { k = 4; // two token lookahead exportVocab=TinyBasic; // Call its vocabulary "TinyBasic" //codeGenMakeSwitchThreshold = 2; // Some optimizations //codeGenBitsetTestThreshold = 3; defaultErrorHandler = false; // Don't generate parser error handlers //analyzerDebug=true; buildAST = true;}{ Context theContext=null;}imaginaryTokenDefinitions : SLIST TYPE PROGRAM_DEF SUBROUTINE_DEF FUNCTION_DEF EXIT_MODULE PARAMETERS PARAMETER_DEF LABELED_STAT NUMBERED_STAT UNARY_MINUS UNARY_PLUS CASE_GROUP ARGLIST FOR_LOOP FOR_FROM FOR_TO FOR_BY FOR_BY_ONE FOR_BODY INT_FN_EXECUTE FLT_FN_EXECUTE STR_FN_EXECUTE SUB_EXECUTE EQ_COMP INDEX_OP SUBSTRING_OP DOT ARRAY1D ARRAY2D ARRAY3D ARRAY1D_PROXY ARRAY2D_PROXY ARRAY3D_PROXY VAR_PROXY WHEN_ERROR_CALL WHEN_ERROR_IN PRINT_ASCII PRINT_TAB PRINT_NUMERIC PRINT_STRING PRINT_COMMA PRINT_SEMI IF_THEN_BLOCK IF_BLOCK ELSE_IF_BLOCK ELSE_BLOCK CODE_BLOCK CONDITION ; // Compilation Unit: In TinyBasic, this is a single file. This is the start// rule for this parsercompilationUnit[Context context] { theContext=context; //new Context(); } : // A compilation unit starts with an optional program definition ( programDefinition | /* nothing */ ) // Next we have a series of zero or more sub/function blocks ( subroutineDefinition | functionDefinition )* EOF! ;// PROGRAM ( parameter, parameter)programDefinition options {defaultErrorHandler = true;} // let ANTLR handle errors { Vector pVector=null; } : "program"! { //#p.setType(PROGRAM_DEF,"PROGRAM_DEF"); theContext.setProgramScope(new ProgramScope(theContext.getCurrentScope())); } pVector=parameters eol! // now parse the body cb:procedureBlock quit:"end" eol! { #quit.setType(EXIT_MODULE); #programDefinition = #(#[PROGRAM_DEF,"PROGRAM_DEF"],#programDefinition); theContext.popScope(); } ;// SUB IDENT ( parameter)*subroutineDefinition options {defaultErrorHandler = true;} // let ANTLR handle errors { Vector pVector=null; } : p:"sub"! n:subName { theContext.pushScope(new SubroutineScope(theContext.getCurrentScope())); } pVector=params:parameters eol! // now parse the body of the class cb:procedureBlock quit:"end" "sub"! eol! { #quit.setType(EXIT_MODULE); DTCodeType sub; #subroutineDefinition = #(#[SUBROUTINE_DEF,"SUBROUTINE_DEF"],#subroutineDefinition); sub=new DTSubroutine(#subroutineDefinition, #cb,theContext.getCurrentScope(),pVector,#n.getText()); theContext.popScope(); theContext.insertSubroutine(#n.getText(),sub); } ;// FUNCTION IDENT ( parameter)*functionDefinition options {defaultErrorHandler = true;} // let ANTLR handle errors { int fnType=0; Vector pVector=null; } : p:"function"^ fnType=n:newFunction {#p.setType(FUNCTION_DEF);} { theContext.pushScope(new FunctionScope(theContext.getCurrentScope())); } pVector=params:parameters eol! // now parse the body of the class cb:procedureBlock quit:"end" "function"! eol! { #quit.setType(EXIT_MODULE); DTCodeType fnc; fnc=new DTFunction(fnType,#params,#cb,theContext.getCurrentScope(),pVector,#n.getText()); #functionDefinition = #(#[FUNCTION_DEF,"FUNCTION_DEF"],#functionDefinition); theContext.popScope(); theContext.insertFunction(#n.getText(),fnc); } ; //funcName// :// INT_FN// | FLT_FN// | STR_FN// ;newFunction returns [int t] { t=0;} : INT_FN { t=INT_FN; } | STR_FN { t=STR_FN; } | FLT_FN { t=FLT_FN; } ;// This is the body of a procedure. procedureBlock : codeBlock //{#procedureBlock = #([OBJBLOCK, "OBJBLOCK"], #procedureBlock);} ;statement : nl ( singleStatement | ifStatements | compoundStatement ) ;parameters returns [ Vector v ] { v=new Vector(); } : ( (LPAREN)=> LPAREN! parameterDeclarationList[v] RPAREN! | ) ;// A list of formal parametersparameterDeclarationList [ Vector v] { DTDataType tbd=null; } : tbd=parameterDeclaration { v.addElement(tbd); } ( COMMA! tbd=parameterDeclaration { v.addElement(tbd); } )* {#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"], #parameterDeclarationList);} ;parameterDeclaration returns [DTDataType arg] { int varType=0; arg=null; } : varType=v:newVariable ( LPAREN! //d1:integerExpression ( COMMA! //d2:integerExpression ( COMMA! //d3:integerExpression { arg=new DTDataTypeProxy(varType,theContext.getCurrentScope(),3); //arg=new DTArray3DProxy(varType,theContext.getCurrentScope()); //#parameterDeclaration = #([ARRAY3D_PROXY], #parameterDeclaration); } | { arg=new DTDataTypeProxy(varType,theContext.getCurrentScope(),2); //arg=new DTArray2DProxy(varType,theContext.getCurrentScope()); //#parameterDeclaration = #([ARRAY2D_PROXY], #parameterDeclaration); } ) | { arg=new DTDataTypeProxy(varType,theContext.getCurrentScope(),1); //arg=new DTArray1DProxy(varType,theContext.getCurrentScope()); //#parameterDeclaration = #([ARRAY1D_PROXY], #parameterDeclaration); } ) RPAREN! | { arg=new DTDataTypeProxy(varType,theContext.getCurrentScope(),0); //#parameterDeclaration = #([VAR_PROXY], #parameterDeclaration); } ) { #parameterDeclaration = #([VAR_PROXY], #parameterDeclaration); theContext.insertVariable(#v.getText(),arg); } ; compoundStatement : forNextBlock | doUntilLoopBlock | doLoopUntilBlock | selectCaseBlock | eventCompoundStatements ;ifThenBlock : ifBlock ( options {
warnWhenFollowAmbig = false;
} : elseIfBlock )* ( options {
warnWhenFollowAmbig = false;
} : elseBlock )? endIfBlock { #ifThenBlock = #(#[IF_THEN_BLOCK,"IF_THEN_BLOCK"],#ifThenBlock);} ;ifStatements : (ifStatement)=> ifStatement | ifThenBlock ;ifStatement : "if"! condition "then"! singleStatement eol! ; ifBlock : "if"! condition "then"! eol! codeBlock { #ifBlock = #(#[IF_BLOCK,"IF_BLOCK"],#ifBlock);} ;elseIfBlock : nl ("else"! "if"! | "elseif"! ) condition "then"! eol! codeBlock { #elseIfBlock = #(#[ELSE_IF_BLOCK,"ELSE_IF_BLOCK"],#elseIfBlock);} ;elseBlock : nl "else"! eol! codeBlock { #elseBlock = #(#[ELSE_BLOCK,"ELSE_BLOCK"],#elseBlock);} ;endIfBlock : nl ("end"! "if"! | "endif"! ) eol! ;condition : relationalExpression { #condition = #(#[CONDITION,"CONDITION"],#condition);} ; codeBlock : ( options {
warnWhenFollowAmbig = false;
} : statement )* {#codeBlock = #(#[CODE_BLOCK,"CODE_BLOCK"],#codeBlock);} ;forNextBlock : "for"! ( // I=1 TO 2 (BY 1)? forFrom forTo forBy eol! forBody ) {#forNextBlock = #(#[FOR_LOOP,"FOR_LOOP"],#forNextBlock);} ;// The initializer for a for loopforFrom : numericStore EQ^ numericExpression {#forFrom = #(#[FOR_FROM,"FOR_FROM"],#forFrom);} ;forTo : "to"! numericExpression {#forTo = #(#[FOR_TO,"FOR_TO"],#forTo);} ;forBy : ( "by"! numericExpression {#forBy = #(#[FOR_BY,"FOR_BY"],#forBy);} | {#forBy = #(#[FOR_BY_ONE,"FOR_BY_ONE"],#forBy);} ) ;forBody : codeBlock nextStatement! {#forBody = #(#[FOR_BODY,"FOR_BODY"],#forBody);} ;nextStatement : nl "next" numericStore eol! ;doUntilLoopBlock : "do"! "until"^ condition eol! codeBlock nl "loop"! eol! ;doLoopUntilBlock : "do"^ eol! codeBlock nl "loop"! "until"! condition eol! ;selectCaseBlock : "select"^ "case"! expression eol (casesGroup)* nl "end" "select" eol! ;singleStatement : ( "library"^ STR_CONST | "dim"^ dimensionedVariables | "global"^ parameterDeclarationList[new Vector()] | "beep" | "chain"^ stringExpression ("with" LPAREN! argList RPAREN!)? | "gosub"^ lineLabel | "goto"^ lineLabel | callSubroutineStatement | "return"^ (expression)? | ex:"exit"^ "sub"! {#ex.setType(EXIT_MODULE);} | ("let"!)? assignmentExpression | ("on" numericExpression)=> "on"^ numericExpression ("goto"^ | "gosub"^ ) lineLabel (COMMA! lineLabel)* | eventSingleStatements | "option"^ "base" INT_CONST | "out"^ integerExpression COMMA! integerExpression | "pause"^ (numericExpression)? | "redim"^ dimensionedVariables | "poke"^ integerExpression COMMA! integerExpression COMMA! integerExpression | "randomize"^ integerExpression | graphicsOutput | inputOutput | line_stuff | set_stuff ) eol! ;callSubroutineStatement : call:"call"^ subName (LPAREN! argList RPAREN!)? { #call.setType(SUB_EXECUTE); } ;dimensionedVariables { DTDataType av=null; int varType=0;} : ( varType=v:newVariable LPAREN! d1:integerExpression ( COMMA! d2:integerExpression ( COMMA! d3:integerExpression { av=new DTArray3D(varType,theContext.getCurrentScope()); #dimensionedVariables = #([ARRAY3D, "ARRAY3D"], #dimensionedVariables); } | { av=new DTArray2D(varType,theContext.getCurrentScope()); #dimensionedVariables = #([ARRAY2D, "ARRAY2D"], #dimensionedVariables); } ) | { av=new DTArray1D(varType,theContext.getCurrentScope()); #dimensionedVariables = #([ARRAY1D, "ARRAY1D"], #dimensionedVariables); } ) RPAREN! { theContext.insertVariable(#v.getText(),av);} ) ( COMMA dimensionedVariables )? ; lineLabel : INT_CONST | IDENT ;nl : ( options {
warnWhenFollowAmbig = false;
} : IDENT^ c:COLON! {#c.setType(LABELED_STAT);} | INT_CONST^ {#c.setType(NUMBERED_STAT);} )? ;constant : stringConstant | floatNumber ;binaryReadVariables : ( numericStore | stringStore "until" integerExpression ) (COMMA binaryReadVariables)? ;printList : ( tabExpression | printString | printNumeric ) ( ( c:COMMA { #c.setType(PRINT_COMMA);} | s:SEMI { #s.setType(PRINT_SEMI);} ) (printList)? )? ;tabExpression : "tab"! LPAREN! numericExpression RPAREN! { #tabExpression = #(#[PRINT_TAB,"PRINT_TAB"],#tabExpression);} ;printString : stringExpression { #printString = #(#[PRINT_STRING,"PRINT_STRING"],#printString);} ;printNumeric : numericExpression { #printNumeric = #(#[PRINT_NUMERIC,"PRINT_NUMERIC"],#printNumeric);} ; inputList : ( numericStore | stringStore ) (COMMA inputList)? ; inputOutput : "close"^ (POUND! integerExpression)? //| "cominfo" | "data"^ constant (COMMA! constant)* | "deletefile" stringExpression //| "fileinfo" | "input" ( "binary" (chanNumber)? binaryReadVariables | chanAndPrompt inputList ) | "open" chanNumber stringExpression ( COMMA ( "access" ( "input" | "output" | "outin" | "append" ) | "organization" ( "sequential" | "random" | "stream" | "append" ) | "recsize" integerExpression ) )+ //| "output" | print_ascii | "print" "binary" (chanNumber)? printList | "read" inputList | "restore" ;set_stuff : "set" ( "timer" numericExpression | "loc" LPAREN integerExpression COMMA integerExpression RPAREN | (chanNumber)? specifier integerExpression ) ;print_ascii : "print"! (chanNumber)? ("using" stringExpression)? printList {#print_ascii = #([PRINT_ASCII, "PRINT_ASCII"], #print_ascii);} ; specifier : "margin" | "zonewidth" | "address" | "record" ;chanNumber : POUND integerExpression COLON ; prompt : "prompt" stringExpression COLON ;chanAndPrompt : (chanNumber)? (prompt)? ;casesGroup : aCase codeBlock {#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);} ; integerArray : argArray ;symbolicAddress : stringExpression ;deviceAddress : (adapterAddress COMMA!)? primaryAddress (COMMA! secondaryAddress)? ; primaryAddress : integerExpression ; secondaryAddress : integerExpression ; adapterAddress : stringExpression | "@" integerExpression ;combinationAddress : (deviceAddress)=> deviceAddress | adapterAddress ;aCase : "case"^ expression (COMMA! expression)* eol! ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -