diff --git a/pom.xml b/pom.xml
index a1d2766..c96715f 100755
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
An approximate grammar for Visual Basic 6.0
org.antlr-grammars
vb6grammar
- 1.3.0
+ 1.4.0
jar
diff --git a/src/main/antlr4/org/vb6/VisualBasic6.g4 b/src/main/antlr4/org/vb6/VisualBasic6.g4
index 7ae3e90..bb3bc33 100755
--- a/src/main/antlr4/org/vb6/VisualBasic6.g4
+++ b/src/main/antlr4/org/vb6/VisualBasic6.g4
@@ -1,5 +1,5 @@
/*
-* Copyright (C) 2014 Ulrich Wolffgang
+* Copyright (C) 2016 Ulrich Wolffgang
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
@@ -44,6 +44,10 @@
*
* Change log:
*
+* v1.4
+* - erase statement fix
+* - explicit token definition
+*
* v1.3
* - call statement precedence
*
@@ -125,7 +129,7 @@ moduleBodyElement :
moduleBlock : block;
-attributeStmt : ATTRIBUTE WS implicitCallStmt_InStmt WS? EQ WS? literal (WS? ',' WS? literal)*;
+attributeStmt : ATTRIBUTE WS implicitCallStmt_InStmt WS? EQ WS? literal (WS? COMMA WS? literal)*;
block : blockStmt (NEWLINE+ WS? blockStmt)*;
@@ -154,7 +158,6 @@ blockStmt :
| goToStmt
| ifThenElseStmt
| implementsStmt
- | implicitCallStmt_InBlock
| inputStmt
| killStmt
| letStmt
@@ -197,12 +200,13 @@ blockStmt :
| widthStmt
| withStmt
| writeStmt
+ | implicitCallStmt_InBlock
;
// statements ----------------------------------
-appactivateStmt : APPACTIVATE WS valueStmt (WS? ',' WS? valueStmt)?;
+appactivateStmt : APPACTIVATE WS valueStmt (WS? COMMA WS? valueStmt)?;
beepStmt : BEEP;
@@ -210,15 +214,15 @@ chdirStmt : CHDIR WS valueStmt;
chdriveStmt : CHDRIVE WS valueStmt;
-closeStmt : CLOSE (WS valueStmt (WS? ',' WS? valueStmt)*)?;
+closeStmt : CLOSE (WS valueStmt (WS? COMMA WS? valueStmt)*)?;
-constStmt : (visibility WS)? CONST WS constSubStmt (WS? ',' WS? constSubStmt)*;
+constStmt : (visibility WS)? CONST WS constSubStmt (WS? COMMA WS? constSubStmt)*;
constSubStmt : ambiguousIdentifier typeHint? (WS asTypeClause)? WS? EQ WS? valueStmt;
dateStmt : DATE WS? EQ WS? valueStmt;
-declareStmt : (visibility WS)? DECLARE WS (FUNCTION | SUB) WS ambiguousIdentifier WS LIB WS STRINGLITERAL (WS ALIAS WS STRINGLITERAL)? (WS? argList)? (WS asTypeClause)?;
+declareStmt : (visibility WS)? DECLARE WS (FUNCTION typeHint? | SUB) WS ambiguousIdentifier typeHint? WS LIB WS STRINGLITERAL (WS ALIAS WS STRINGLITERAL)? (WS? argList)? (WS asTypeClause)?;
deftypeStmt :
(
@@ -226,10 +230,10 @@ deftypeStmt :
DEFSNG | DEFDBL | DEFDEC | DEFDATE |
DEFSTR | DEFOBJ | DEFVAR
) WS
- letterrange (WS? ',' WS? letterrange)*
+ letterrange (WS? COMMA WS? letterrange)*
;
-deleteSettingStmt : DELETESETTING WS valueStmt WS? ',' WS? valueStmt (WS? ',' WS? valueStmt)?;
+deleteSettingStmt : DELETESETTING WS valueStmt WS? COMMA WS? valueStmt (WS? COMMA WS? valueStmt)?;
doLoopStmt :
DO NEWLINE+
@@ -255,7 +259,7 @@ enumerationStmt:
enumerationStmt_Constant : ambiguousIdentifier (WS? EQ WS? valueStmt)? NEWLINE+;
-eraseStmt : ERASE WS valueStmt;
+eraseStmt : ERASE WS valueStmt (WS? COMMA WS? valueStmt)*;
errorStmt : ERROR WS valueStmt;
@@ -263,7 +267,7 @@ eventStmt : (visibility WS)? EVENT WS ambiguousIdentifier WS? argList;
exitStmt : EXIT_DO | EXIT_FOR | EXIT_FUNCTION | EXIT_PROPERTY | EXIT_SUB;
-filecopyStmt : FILECOPY WS valueStmt WS? ',' WS? valueStmt;
+filecopyStmt : FILECOPY WS valueStmt WS? COMMA WS? valueStmt;
forEachStmt :
FOR WS EACH WS ambiguousIdentifier typeHint? WS IN WS valueStmt NEWLINE+
@@ -283,7 +287,7 @@ functionStmt :
END_FUNCTION
;
-getStmt : GET WS valueStmt WS? ',' WS? valueStmt? WS? ',' WS? valueStmt;
+getStmt : GET WS valueStmt WS? COMMA WS? valueStmt? WS? COMMA WS? valueStmt;
goSubStmt : GOSUB WS valueStmt;
@@ -313,17 +317,17 @@ ifElseBlockStmt :
implementsStmt : IMPLEMENTS WS ambiguousIdentifier;
-inputStmt : INPUT WS valueStmt (WS? ',' WS? valueStmt)+;
+inputStmt : INPUT WS valueStmt (WS? COMMA WS? valueStmt)+;
killStmt : KILL WS valueStmt;
letStmt : (LET WS)? implicitCallStmt_InStmt WS? (EQ | PLUS_EQ | MINUS_EQ) WS? valueStmt;
-lineInputStmt : LINE_INPUT WS valueStmt WS? ',' WS? valueStmt;
+lineInputStmt : LINE_INPUT WS valueStmt WS? COMMA WS? valueStmt;
loadStmt : LOAD WS valueStmt;
-lockStmt : LOCK WS valueStmt (WS? ',' WS? valueStmt (WS TO WS valueStmt)?)?;
+lockStmt : LOCK WS valueStmt (WS? COMMA WS? valueStmt (WS TO WS valueStmt)?)?;
lsetStmt : LSET WS implicitCallStmt_InStmt WS? EQ WS? valueStmt;
@@ -352,9 +356,9 @@ nameStmt : NAME WS valueStmt WS AS WS valueStmt;
onErrorStmt : ON_ERROR WS (GOTO WS valueStmt | RESUME WS NEXT);
-onGoToStmt : ON WS valueStmt WS GOTO WS valueStmt (WS? ',' WS? valueStmt)*;
+onGoToStmt : ON WS valueStmt WS GOTO WS valueStmt (WS? COMMA WS? valueStmt)*;
-onGoSubStmt : ON WS valueStmt WS GOSUB WS valueStmt (WS? ',' WS? valueStmt)*;
+onGoSubStmt : ON WS valueStmt WS GOSUB WS valueStmt (WS? COMMA WS? valueStmt)*;
openStmt :
OPEN WS valueStmt WS FOR WS (APPEND | BINARY | INPUT | OUTPUT | RANDOM)
@@ -365,8 +369,8 @@ openStmt :
;
outputList :
- outputList_Expression (WS? (';' | ',') WS? outputList_Expression?)*
- | outputList_Expression? (WS? (';' | ',') WS? outputList_Expression?)+
+ outputList_Expression (WS? (SEMICOLON | COMMA) WS? outputList_Expression?)*
+ | outputList_Expression? (WS? (SEMICOLON | COMMA) WS? outputList_Expression?)+
;
outputList_Expression :
@@ -374,10 +378,10 @@ outputList_Expression :
| (SPC | TAB) (WS? LPAREN WS? argsCall WS? RPAREN)?
;
-printStmt : PRINT WS valueStmt WS? ',' (WS? outputList)?;
+printStmt : PRINT WS valueStmt WS? COMMA (WS? outputList)?;
propertyGetStmt :
- (visibility WS)? (STATIC WS)? PROPERTY_GET WS ambiguousIdentifier (WS? argList)? (WS asTypeClause)? NEWLINE+
+ (visibility WS)? (STATIC WS)? PROPERTY_GET WS ambiguousIdentifier typeHint? (WS? argList)? (WS asTypeClause)? NEWLINE+
(block NEWLINE+)?
END_PROPERTY
;
@@ -394,13 +398,13 @@ propertyLetStmt :
END_PROPERTY
;
-putStmt : PUT WS valueStmt WS? ',' WS? valueStmt? WS? ',' WS? valueStmt;
+putStmt : PUT WS valueStmt WS? COMMA WS? valueStmt? WS? COMMA WS? valueStmt;
raiseEventStmt : RAISEEVENT WS ambiguousIdentifier (WS? LPAREN WS? (argsCall WS?)? RPAREN)?;
randomizeStmt : RANDOMIZE (WS valueStmt)?;
-redimStmt : REDIM WS (PRESERVE WS)? redimSubStmt (WS?',' WS? redimSubStmt)*;
+redimStmt : REDIM WS (PRESERVE WS)? redimSubStmt (WS? COMMA WS? redimSubStmt)*;
redimSubStmt : implicitCallStmt_InStmt WS? LPAREN WS? subscripts WS? RPAREN (WS asTypeClause)?;
@@ -414,11 +418,11 @@ rmdirStmt : RMDIR WS valueStmt;
rsetStmt : RSET WS implicitCallStmt_InStmt WS? EQ WS? valueStmt;
-savepictureStmt : SAVEPICTURE WS valueStmt WS? ',' WS? valueStmt;
+savepictureStmt : SAVEPICTURE WS valueStmt WS? COMMA WS? valueStmt;
-saveSettingStmt : SAVESETTING WS valueStmt WS? ',' WS? valueStmt WS? ',' WS? valueStmt WS? ',' WS? valueStmt;
+saveSettingStmt : SAVESETTING WS valueStmt WS? COMMA WS? valueStmt WS? COMMA WS? valueStmt WS? COMMA WS? valueStmt;
-seekStmt : SEEK WS valueStmt WS? ',' WS? valueStmt;
+seekStmt : SEEK WS valueStmt WS? COMMA WS? valueStmt;
selectCaseStmt :
SELECT WS CASE WS valueStmt NEWLINE+
@@ -427,7 +431,7 @@ selectCaseStmt :
;
sC_Case :
- CASE WS sC_Cond WS? (':'? NEWLINE* | NEWLINE+)
+ CASE WS sC_Cond WS? (COLON? NEWLINE* | NEWLINE+)
(block NEWLINE+)?
;
@@ -435,13 +439,13 @@ sC_Case :
sC_Cond :
ELSE # caseCondElse
| IS WS? comparisonOperator WS? valueStmt # caseCondIs
- | valueStmt (WS? ',' WS? valueStmt)* # caseCondValue
- | INTEGERLITERAL WS TO WS valueStmt (WS? ',' WS? valueStmt)* # caseCondTo
+ | valueStmt (WS? COMMA WS? valueStmt)* # caseCondValue
+ | INTEGERLITERAL WS TO WS valueStmt (WS? COMMA WS? valueStmt)* # caseCondTo
;
-sendkeysStmt : SENDKEYS WS valueStmt (WS? ',' WS? valueStmt)?;
+sendkeysStmt : SENDKEYS WS valueStmt (WS? COMMA WS? valueStmt)?;
-setattrStmt : SETATTR WS valueStmt WS? ',' WS? valueStmt;
+setattrStmt : SETATTR WS valueStmt WS? COMMA WS? valueStmt;
setStmt : SET WS implicitCallStmt_InStmt WS? EQ WS? valueStmt;
@@ -467,13 +471,13 @@ typeOfStmt : TYPEOF WS valueStmt (WS IS WS type)?;
unloadStmt : UNLOAD WS valueStmt;
-unlockStmt : UNLOCK WS valueStmt (WS? ',' WS? valueStmt (WS TO WS valueStmt)?)?;
+unlockStmt : UNLOCK WS valueStmt (WS? COMMA WS? valueStmt (WS TO WS valueStmt)?)?;
// operator precedence is represented by rule order
valueStmt :
literal # vsLiteral
| implicitCallStmt_InStmt # vsICS
- | LPAREN WS? valueStmt (WS? ',' WS? valueStmt)* RPAREN # vsStruct
+ | LPAREN WS? valueStmt (WS? COMMA WS? valueStmt)* RPAREN # vsStruct
| NEW WS valueStmt # vsNew
| typeOfStmt # vsTypeOf
| midStmt # vsMid
@@ -509,7 +513,7 @@ valueStmt :
variableStmt : (DIM | STATIC | visibility) WS (WITHEVENTS WS)? variableListStmt;
-variableListStmt : variableSubStmt (WS? ',' WS? variableSubStmt)*;
+variableListStmt : variableSubStmt (WS? COMMA WS? variableSubStmt)*;
variableSubStmt : ambiguousIdentifier (WS? LPAREN WS? (subscripts WS?)? RPAREN WS?)? typeHint? (WS asTypeClause)?;
@@ -519,7 +523,7 @@ whileWendStmt :
WEND
;
-widthStmt : WIDTH WS valueStmt WS? ',' WS? valueStmt;
+widthStmt : WIDTH WS valueStmt WS? COMMA WS? valueStmt;
withStmt :
WITH WS implicitCallStmt_InStmt NEWLINE+
@@ -527,7 +531,7 @@ withStmt :
END_WITH
;
-writeStmt : WRITE WS valueStmt WS? ',' (WS? outputList)?;
+writeStmt : WRITE WS valueStmt WS? COMMA (WS? outputList)?;
// complex call statements ----------------------------------
@@ -541,7 +545,7 @@ explicitCallStmt :
eCS_ProcedureCall : CALL WS ambiguousIdentifier typeHint? (WS? LPAREN WS? argsCall WS? RPAREN)?;
// parantheses are required in case of args -> empty parantheses are removed
-eCS_MemberProcedureCall : CALL WS implicitCallStmt_InStmt? '.' ambiguousIdentifier typeHint? (WS? LPAREN WS? argsCall WS? RPAREN)?;
+eCS_MemberProcedureCall : CALL WS implicitCallStmt_InStmt? DOT ambiguousIdentifier typeHint? (WS? LPAREN WS? argsCall WS? RPAREN)?;
implicitCallStmt_InBlock :
@@ -554,7 +558,7 @@ implicitCallStmt_InBlock :
// certainIdentifier instead of ambiguousIdentifier for preventing ambiguity with statement keywords
iCS_B_ProcedureCall : certainIdentifier (WS argsCall)?;
-iCS_B_MemberProcedureCall : implicitCallStmt_InStmt? '.' ambiguousIdentifier typeHint? (WS argsCall)? dictionaryCallStmt?;
+iCS_B_MemberProcedureCall : implicitCallStmt_InStmt? DOT ambiguousIdentifier typeHint? (WS argsCall)? dictionaryCallStmt?;
// iCS_S_MembersCall first, so that member calls are not resolved as separate iCS_S_VariableOrProcedureCalls
@@ -571,29 +575,29 @@ iCS_S_ProcedureOrArrayCall : (ambiguousIdentifier | baseType) typeHint? WS? LPAR
iCS_S_MembersCall : (iCS_S_VariableOrProcedureCall | iCS_S_ProcedureOrArrayCall)? iCS_S_MemberCall+ dictionaryCallStmt?;
-iCS_S_MemberCall : '.' (iCS_S_VariableOrProcedureCall | iCS_S_ProcedureOrArrayCall);
+iCS_S_MemberCall : DOT (iCS_S_VariableOrProcedureCall | iCS_S_ProcedureOrArrayCall);
iCS_S_DictionaryCall : dictionaryCallStmt;
// atomic call statements ----------------------------------
-argsCall : (argCall? WS? (',' | ';') WS?)* argCall (WS? (',' | ';') WS? argCall?)*;
+argsCall : (argCall? WS? (COMMA | SEMICOLON) WS?)* argCall (WS? (COMMA | SEMICOLON) WS? argCall?)*;
argCall : ((BYVAL | BYREF | PARAMARRAY) WS)? valueStmt;
-dictionaryCallStmt : '!' ambiguousIdentifier typeHint?;
+dictionaryCallStmt : EXCLAMATIONMARK ambiguousIdentifier typeHint?;
// atomic rules for statements
-argList : LPAREN (WS? arg (WS? ',' WS? arg)*)? WS? RPAREN;
+argList : LPAREN (WS? arg (WS? COMMA WS? arg)*)? WS? RPAREN;
arg : (OPTIONAL WS)? ((BYVAL | BYREF) WS)? (PARAMARRAY WS)? ambiguousIdentifier (WS? LPAREN WS? RPAREN)? (WS asTypeClause)? (WS? argDefaultValue)?;
argDefaultValue : EQ WS? (literal | ambiguousIdentifier);
-subscripts : subscript (WS? ',' WS? subscript)*;
+subscripts : subscript (WS? COMMA WS? subscript)*;
subscript : (valueStmt WS TO WS)? valueStmt;
@@ -616,19 +620,19 @@ certainIdentifier :
comparisonOperator : LT | LEQ | GT | GEQ | EQ | NEQ | IS | LIKE;
-complexType : ambiguousIdentifier ('.' ambiguousIdentifier)*;
+complexType : ambiguousIdentifier (DOT ambiguousIdentifier)*;
fieldLength : MULT WS? (INTEGERLITERAL | ambiguousIdentifier);
letterrange : certainIdentifier (WS? MINUS WS? certainIdentifier)?;
-lineLabel : ambiguousIdentifier ':';
+lineLabel : ambiguousIdentifier COLON;
literal : COLORLITERAL | DATELITERAL | DOUBLELITERAL | FILENUMBER | INTEGERLITERAL | STRINGLITERAL | TRUE | FALSE | NOTHING | NULL;
type : (baseType | complexType) (WS? LPAREN WS? RPAREN)?;
-typeHint : '&' | '%' | '#' | '!' | '@' | '$';
+typeHint : AMPERSAND | AT | DOLLAR | EXCLAMATIONMARK | HASH | PERCENT;
visibility : PRIVATE | PUBLIC | FRIEND | GLOBAL;
@@ -756,10 +760,10 @@ LOCK_READ : L O C K ' ' R E A D;
LOCK_WRITE : L O C K ' ' W R I T E;
LOCK_READ_WRITE : L O C K ' ' R E A D ' ' W R I T E;
LSET : L S E T;
-MACRO_IF : '#' I F;
-MACRO_ELSEIF : '#' E L S E I F;
-MACRO_ELSE : '#' E L S E;
-MACRO_END_IF : '#' E N D ' ' I F;
+MACRO_IF : HASH I F;
+MACRO_ELSEIF : HASH E L S E I F;
+MACRO_ELSE : HASH E L S E;
+MACRO_END_IF : HASH E N D ' ' I F;
ME : M E;
MID : M I D;
MKDIR : M K D I R;
@@ -841,10 +845,17 @@ XOR : X O R;
// symbols
AMPERSAND : '&';
ASSIGN : ':=';
+AT : '@';
+COLON : ':';
+COMMA : ',';
DIV : '\\' | '/';
+DOLLAR : '$';
+DOT : '.';
EQ : '=';
+EXCLAMATIONMARK : '!';
GEQ : '>=';
GT : '>';
+HASH : '#';
LEQ : '<=';
LPAREN : '(';
LT : '<';
@@ -852,21 +863,23 @@ MINUS : '-';
MINUS_EQ : '-=';
MULT : '*';
NEQ : '<>';
+PERCENT : '%';
PLUS : '+';
PLUS_EQ : '+=';
POW : '^';
RPAREN : ')';
+SEMICOLON : ';';
L_SQUARE_BRACKET : '[';
R_SQUARE_BRACKET : ']';
// literals
STRINGLITERAL : '"' (~["\r\n] | '""')* '"';
-DATELITERAL : '#' (~[#\r\n])* '#';
-COLORLITERAL : '&H' [0-9A-F]+ '&'?;
-INTEGERLITERAL : (PLUS|MINUS)? ('0'..'9')+ ( ('e' | 'E') INTEGERLITERAL)* ('#' | '&')?;
-DOUBLELITERAL : (PLUS|MINUS)? ('0'..'9')* '.' ('0'..'9')+ ( ('e' | 'E') (PLUS|MINUS)? ('0'..'9')+)* ('#' | '&')?;
-FILENUMBER : '#' LETTERORDIGIT+;
+DATELITERAL : HASH (~[#\r\n])* HASH;
+COLORLITERAL : '&H' [0-9A-F]+ AMPERSAND?;
+INTEGERLITERAL : (PLUS|MINUS)? ('0'..'9')+ ( ('e' | 'E') INTEGERLITERAL)* (HASH | AMPERSAND)?;
+DOUBLELITERAL : (PLUS|MINUS)? ('0'..'9')* DOT ('0'..'9')+ ( ('e' | 'E') (PLUS|MINUS)? ('0'..'9')+)* (HASH | AMPERSAND)?;
+FILENUMBER : HASH LETTERORDIGIT+;
// identifier
@@ -875,8 +888,8 @@ IDENTIFIER : LETTER LETTERORDIGIT*;
// whitespace, line breaks, comments, ...
LINE_CONTINUATION : ' ' '_' '\r'? '\n' -> skip;
-NEWLINE : WS? ('\r'? '\n' | ':' ' ') WS?;
-COMMENT : WS? ('\'' | ':'? REM ' ') (LINE_CONTINUATION | ~('\n' | '\r'))* -> skip;
+NEWLINE : WS? ('\r'? '\n' | COLON ' ') WS?;
+COMMENT : WS? ('\'' | COLON? REM ' ') (LINE_CONTINUATION | ~('\n' | '\r'))* -> skip;
WS : [ \t]+;