albertodemichelis / squirrel

Official repository for the programming language Squirrel
http://www.squirrel-lang.org
MIT License
913 stars 156 forks source link

Squirrel grammar #237

Open mingodad opened 3 years ago

mingodad commented 3 years ago

I'm testing this interesting parser generator https://ssw.jku.at/Research/Projects/Coco/ and as exercise I'm building a Squirrel/SquiLu grammar with it.

As usual any feedback is welcome !

This is the initial CocoR grammar just in case someone else want to try (edited with my latest):


#include "Scanner.nut"

COMPILER Squirrel

CHARACTERS
    letter    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_".
    oct        = '0'..'7'.
    digit     = '0'..'9'.
    nzdigit    = '1'..'9'.
    cr        = '\r'.
    lf        = '\n'.
    tab       = '\t'.
    stringCh  = ANY - '"' - '\\' - cr - lf.
    charCh    = ANY - '\'' - '\\' - cr - lf.
    printable = '\u0020' .. '\u007e'.
    hex        = digit + 'a'..'f' + 'A'..'F'.

TOKENS
    TK_IDENTIFIER     = letter { letter | digit }.

    TK_FLOAT = ( '.' digit {digit} [('e'|'E')  ['+'|'-'] digit {digit}]
                         | digit {digit} '.' {digit} [('e'|'E')  ['+'|'-'] digit {digit}]
                         | digit {digit} ('e'|'E')  ['+'|'-'] digit {digit}
                         )
                         .

    TK_INTEGER   = ( /*nz*/ digit {digit}
                         //| '0' {oct}
                         | ("0x"|"0X") hex {hex}
                         )
                         .

    TK_STRING_LITERAL    = ['@'] '"' {stringCh |  '\\' (printable | ['\r'] '\n')} '"'
            | "'" { charCh | '\\' (printable | ['\r'] '\n')} "'"
            .

    badString = '"' {stringCh | '\\' printable} (cr | lf)
            | "'" {charCh | '\\' printable } (cr | lf)
            .

    TK_AND = "&&".
    TK_ATTR_CLOSE = "/>".
    TK_ATTR_OPEN = "</".
    TK_BASE = "base".
    TK_BIT_AND_EQ = "&=".
    TK_BIT_OR_EQ = "|=".
    TK_BIT_SHIFT_LEFT_EQ = "<<=".
    TK_BIT_SHIFT_RIGHT_EQ = ">>=".
    TK_BIT_XOR_EQ = "^=".
    TK_BREAK = "break".
    TK_CASE = "case".
    TK_CATCH = "catch".
    TK_CLASS = "class".
    TK_CLONE = "clone".
    TK_CONST = "const".
    TK_CONTINUE = "continue".
    TK_CONSTRUCTOR = "constructor".
    TK_DEFAULT = "default".
    TK_DELETE = "delete".
    TK_DIVEQ = "/=".
    TK_DO = "do".
    TK_DOUBLE_COLON = "::".
    TK_EQ = "==".
    TK_ELSE = "else".
    TK_ENUM = "enum".
    TK_FALSE = "false".
    TK___FILE__ = "__FILE__".
    TK_FOREACH = "foreach".
    TK_FOR = "for".
    TK_FUNCTION = "function".
    TK___FUNCTION__ = "__FUNCTION__".
    TK_GOTO = "goto".
    TK_GE = ">=".
    TK_IF = "if".
    TK_IN = "in".
    TK_INSTANCEOF = "instanceof".
    TK_LE = "<=".
    TK___LINE__ = "__LINE__".
    TK_LOCAL = "local".
    TK_MINUSEQ = "-=".
    TK_MINUSMINUS = "--".
    TK_MODEQ = "%=".
    TK_MULEQ = "*=".
    TK_NE = "!=".
    TK_NEWSLOT = "<-".
    TK_NULL = "null".
    TK_OR = "||".
    TK_PLUSEQ = "+=".
    TK_PLUSPLUS = "++".
    TK_RAWCALL = "rawcall".
    TK_RESUME = "resume".
    TK_RETURN = "return".
    TK_SHIFTL = ">>".
    TK_SHIFTR = "<<".
    TK_STATIC = "static".
    TK_SWITCH = "switch".
    TK_THIS = "this".
    TK_THROW = "throw".
    TK_3WAYSCMP = "<=>".
    TK_TRUE = "true".
    TK_TRY = "try".
    TK_TYPEOF = "typeof".
    TK_USHIFTR = ">>>".
    TK_VARPARAMS = "...".
    TK_WHILE = "while".
    TK_YIELD = "yield".

COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf

IGNORE cr + lf + tab

PRODUCTIONS

Squirrel = {Statement}
    .

Statement =
    (
    IfStatement
    | WhileStatement
    | DoWhileStatement
    | ForStatement
    | ForEachStatement
    | SwitchStatement
    | LocalDeclStatement
    | ReturnStatement
    | YeldStatement
    | BreakStatement
    | ContinueStatement
    | FunctionStatement
    | ClassStatement
    | EnumStatement
    | Statements
    | TryCatchStatement
    | ThrowStatement
    | ConstStatement
    | CommaExpr
    ) [';']
    .

IfStatement = TK_IF '(' CommaExpr ')' IfBlock [TK_ELSE IfBlock]
    .

IfBlock = Statement
    .

WhileStatement = TK_WHILE '(' CommaExpr ')' Statement
    .

DoWhileStatement = TK_DO Statement TK_WHILE '(' CommaExpr ')'
    .

ForStatement = TK_FOR '(' [LocalDeclStatement | CommaExpr] ';' [CommaExpr] ';' [CommaExpr] ')' Statement
    .

ForEachStatement = TK_FOREACH '(' TK_IDENTIFIER [',' TK_IDENTIFIER] TK_IN Expression ')' Statement
    .

SwitchStatement = TK_SWITCH '(' CommaExpr ')'  '{' {CaseStatement} [TK_DEFAULT ':' Statement] '}'
    .

CaseStatement = TK_CASE ExpressionScalar ':' [Statement]
    .

LocalDeclStatement = TK_LOCAL
    (
    TK_FUNCTION TK_IDENTIFIER CreateFunction
    |  AssignExpr {',' AssignExpr}
    )
    .

AssignExpr = TK_IDENTIFIER ['=' Expression]
    .

ReturnStatement = TK_RETURN [CommaExpr]
    .

YeldStatement = TK_YIELD [CommaExpr]
    .

BreakStatement = TK_BREAK
    .

ContinueStatement = TK_CONTINUE
    .

FunctionStatement = TK_FUNCTION TK_IDENTIFIER {"::" (TK_IDENTIFIER | TK_CONSTRUCTOR)} CreateFunction
    .

CreateFunction =  FunctionParams Statement
    .

CreateLambda =  FunctionParams Expression
    .

FunctionParams =  '(' [TK_VARPARAMS | OneFunctionParam {',' OneFunctionParam}] ')'
    .

OneFunctionParam =  TK_IDENTIFIER ['=' Expression]
    .

ClassStatement =
    TK_CLASS PrefixedExpr
    (';' | ClassExp)
    .

ClassExp = ["extends" Expression]
        [TK_ATTR_OPEN {ParseTable} TK_ATTR_CLOSE]
        '{' {ParseClass} '}'
    .

ParseClass = ParseTableOrClass [';']
    .

ParseTable = ParseTableOrClass [',']
    .

ParseTableOrClass =
    ([TK_STATIC] TK_FUNCTION TK_IDENTIFIER | TK_CONSTRUCTOR) CreateFunction
    | '[' CommaExpr ']' '=' Expression
    | TK_STRING_LITERAL ':' Expression
    | TK_IDENTIFIER '=' Expression
    .

EnumStatement = TK_ENUM TK_IDENTIFIER '{' EnumItem {',' EnumItem} '}'
    .

EnumItem = TK_IDENTIFIER ['=' ExpectScalar]
    .

Statements = '{' {Statement} '}'
    .

TryCatchStatement = TK_TRY Statement TK_CATCH '(' TK_IDENTIFIER ')' Statement
    .

ThrowStatement = TK_THROW CommaExpr
    .

ConstStatement = TK_CONST (TK_IDENTIFIER '=' ExpectScalar)
    .

ExpectScalar = (['-'] (TK_INTEGER | TK_FLOAT)) | TK_STRING_LITERAL | TK_TRUE | TK_FALSE
    .

CommaExpr = Expression {',' Expression}
    .

Expression =
    LogicalOrExp [
        ('=' | TK_NEWSLOT | TK_MINUSEQ | TK_PLUSEQ | TK_MULEQ | TK_DIVEQ | TK_MODEQ) Expression
        | '?' Expression ':' Expression
    ]
    .

LogicalOrExp = LogicalAndExp {TK_OR LogicalOrExp}
    .

LogicalAndExp = BitwiseOrExp {TK_AND LogicalAndExp}
    .

BitwiseOrExp = BitwiseXorExp {'|' BitwiseXorExp}
    .

BitwiseXorExp = BitwiseAndExp {'^' BitwiseAndExp}
    .

BitwiseAndExp = EqExp {'&' EqExp}
    .

EqExp = CompExp {(TK_EQ | TK_NE | TK_3WAYSCMP) CompExp}
    .

CompExp = ShiftExp {('>' | '<' | TK_GE | TK_LE | TK_IN | TK_INSTANCEOF) ShiftExp}
    .

ShiftExp = PlusExp {(TK_USHIFTR | TK_SHIFTL | TK_SHIFTR) PlusExp}
    .

PlusExp = MultExp {('+' | '-') MultExp}
    .

MultExp = PrefixedExpr {('*' | '/' | '%') PrefixedExpr}
    .

PrefixedExpr = Factor
    {
        '.' (TK_IDENTIFIER | TK_CONSTRUCTOR)
        | '[' Expression ']'
        | (TK_MINUSMINUS | TK_PLUSPLUS)
        | FunctionCallArgs
    }
    .

Factor =
    TK_STRING_LITERAL
    | TK_BASE
    | TK_IDENTIFIER
    | TK_CONSTRUCTOR
    | TK_THIS
    | TK_DOUBLE_COLON PrefixedExpr
    | TK_NULL
    | TK_INTEGER
    | TK_FLOAT
    | TK_TRUE
    | TK_FALSE
    | '[' [Expression {[','] Expression}] ']'
    | '{' {ParseTable} '}'
    | TK_FUNCTION CreateFunction
    |  FunctionExp
    | TK_CLASS ClassExp
    | UnaryOP
    | TK_RAWCALL FunctionCallArgs
    | PrefixIncDec
    | DeleteExpr
    | '(' CommaExpr ')'
    | TK___LINE__
    | TK___FILE__
    .

FunctionExp = '@' CreateLambda
    .

UnaryOP =
    (
    '-' //(TK_INTEGER | TK_FLOAT)
    | '~' //TK_INTEGER
    | '!'
    | TK_TYPEOF
    | TK_RESUME
    | TK_CLONE
    ) PrefixedExpr
    .

FunctionCallArgs = '(' [Expression {',' Expression}] ')'
    .

PrefixIncDec = (TK_MINUSMINUS | TK_PLUSPLUS) PrefixedExpr
    .

DeleteExpr =
    TK_DELETE PrefixedExpr
    .

ExpressionScalar =
    TK_INTEGER
    | TK_FLOAT
    | TK_STRING_LITERAL
    .

END Squirrel .

And here is the Squirrel EBNF accepted by https://www.bottlecaps.de/rr/ui to create railroad diagrams, copy the grammar bellow and paste on the Edit Grammar tab then switch to the View Diagram tab to view the railroad diagram.

//"/*" "*/" "//" lf cr  '+' lf  '+' tab
Squirrel ::=  ( Statement  )*
Statement ::=  ( IfStatement  | WhileStatement  | DoWhileStatement  | ForStatement  | ForEachStatement  | SwitchStatement  | LocalDeclStatement  | ReturnStatement  | YeldStatement  | BreakStatement  | ContinueStatement  | FunctionStatement  | ClassStatement  | EnumStatement  | Statements  | TryCatchStatement  | ThrowStatement  | ConstStatement  | CommaExpr  )  ( ';'  )?
IfStatement ::= TK_IF '(' CommaExpr ')' IfBlock  ( TK_ELSE IfBlock  )?
IfBlock ::= Statement
WhileStatement ::= TK_WHILE '(' CommaExpr ')' Statement
DoWhileStatement ::= TK_DO Statement TK_WHILE '(' CommaExpr ')'
ForStatement ::= TK_FOR '('  ( LocalDeclStatement  | CommaExpr  )? ';'  ( CommaExpr  )? ';'  ( CommaExpr  )? ')' Statement
ForEachStatement ::= TK_FOREACH '(' TK_IDENTIFIER  ( ',' TK_IDENTIFIER  )? TK_IN Expression ')' Statement
SwitchStatement ::= TK_SWITCH '(' CommaExpr ')' '{'  ( CaseStatement  )*  ( TK_DEFAULT ':' Statement  )? '}'
CaseStatement ::= TK_CASE ExpressionScalar ':'  ( Statement  )?
LocalDeclStatement ::= TK_LOCAL  ( TK_FUNCTION TK_IDENTIFIER CreateFunction  | AssignExpr  ( ',' AssignExpr  )*  )
AssignExpr ::= TK_IDENTIFIER  ( '=' Expression  )?
ReturnStatement ::= TK_RETURN  ( CommaExpr  )?
YeldStatement ::= TK_YIELD  ( CommaExpr  )?
BreakStatement ::= TK_BREAK
ContinueStatement ::= TK_CONTINUE
FunctionStatement ::= TK_FUNCTION TK_IDENTIFIER  ( "::"  ( TK_IDENTIFIER  | TK_CONSTRUCTOR  )  )* CreateFunction
CreateFunction ::= FunctionParams Statement
CreateLambda ::= FunctionParams Expression
FunctionParams ::= '('  ( TK_VARPARAMS  | OneFunctionParam  ( ',' OneFunctionParam  )*  )? ')'
OneFunctionParam ::= TK_IDENTIFIER  ( '=' Expression  )?
ClassStatement ::= TK_CLASS PrefixedExpr  ( ';'  | ClassExp  )
ClassExp ::=  ( "extends" Expression  )?  ( TK_ATTR_OPEN  ( ParseTable  )* TK_ATTR_CLOSE  )? '{'  ( ParseClass  )* '}'
ParseClass ::= ParseTableOrClass  ( ';'  )?
ParseTable ::= ParseTableOrClass  ( ','  )?
ParseTableOrClass ::=  (  ( TK_STATIC  )? TK_FUNCTION TK_IDENTIFIER  | TK_CONSTRUCTOR  ) CreateFunction  | '[' CommaExpr ']' '=' Expression  | TK_STRING_LITERAL ':' Expression  | TK_IDENTIFIER '=' Expression
EnumStatement ::= TK_ENUM TK_IDENTIFIER '{' EnumItem  ( ',' EnumItem  )* '}'
EnumItem ::= TK_IDENTIFIER  ( '=' ExpectScalar  )?
Statements ::= '{'  ( Statement  )* '}'
TryCatchStatement ::= TK_TRY Statement TK_CATCH '(' TK_IDENTIFIER ')' Statement
ThrowStatement ::= TK_THROW CommaExpr
ConstStatement ::= TK_CONST  ( TK_IDENTIFIER '=' ExpectScalar  )
ExpectScalar ::=  (  ( '-'  )?  ( TK_INTEGER  | TK_FLOAT  )  )  | TK_STRING_LITERAL  | TK_TRUE  | TK_FALSE
CommaExpr ::= Expression  ( ',' Expression  )*
Expression ::= LogicalOrExp  (  ( '='  | TK_NEWSLOT  | TK_MINUSEQ  | TK_PLUSEQ  | TK_MULEQ  | TK_DIVEQ  | TK_MODEQ  ) Expression  | '?' Expression ':' Expression  )?
LogicalOrExp ::= LogicalAndExp  ( TK_OR LogicalOrExp  )*
LogicalAndExp ::= BitwiseOrExp  ( TK_AND LogicalAndExp  )*
BitwiseOrExp ::= BitwiseXorExp  ( '|' BitwiseXorExp  )*
BitwiseXorExp ::= BitwiseAndExp  ( '^' BitwiseAndExp  )*
BitwiseAndExp ::= EqExp  ( '&' EqExp  )*
EqExp ::= CompExp  (  ( TK_EQ  | TK_NE  | TK_3WAYSCMP  ) CompExp  )*
CompExp ::= ShiftExp  (  ( '>'  | '<'  | TK_GE  | TK_LE  | TK_IN  | TK_INSTANCEOF  ) ShiftExp  )*
ShiftExp ::= PlusExp  (  ( TK_USHIFTR  | TK_SHIFTL  | TK_SHIFTR  ) PlusExp  )*
PlusExp ::= MultExp  (  ( '+'  | '-'  ) MultExp  )*
MultExp ::= PrefixedExpr  (  ( '*'  | '/'  | '%'  ) PrefixedExpr  )*
PrefixedExpr ::= Factor  ( '.'  ( TK_IDENTIFIER  | TK_CONSTRUCTOR  )  | '[' Expression ']'  |  ( TK_MINUSMINUS  | TK_PLUSPLUS  )  | FunctionCallArgs  )*
Factor ::= TK_STRING_LITERAL  | TK_BASE  | TK_IDENTIFIER  | TK_CONSTRUCTOR  | TK_THIS  | TK_DOUBLE_COLON PrefixedExpr  | TK_NULL  | TK_INTEGER  | TK_FLOAT  | TK_TRUE  | TK_FALSE  | '['  ( Expression  (  ( ','  )? Expression  )*  )? ']'  | '{'  ( ParseTable  )* '}'  | TK_FUNCTION CreateFunction  | FunctionExp  | TK_CLASS ClassExp  | UnaryOP  | TK_RAWCALL FunctionCallArgs  | PrefixIncDec  | DeleteExpr  | '(' CommaExpr ')'  | TK___LINE__  | TK___FILE__
FunctionExp ::= '@' CreateLambda
UnaryOP ::=  ( '-'  | '~'  | '!'  | TK_TYPEOF  | TK_RESUME  | TK_CLONE  ) PrefixedExpr
FunctionCallArgs ::= '('  ( Expression  ( ',' Expression  )*  )? ')'
PrefixIncDec ::=  ( TK_MINUSMINUS  | TK_PLUSPLUS  ) PrefixedExpr
DeleteExpr ::= TK_DELETE PrefixedExpr
ExpressionScalar ::= TK_INTEGER  | TK_FLOAT  | TK_STRING_LITERAL

letter ::= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
oct ::= '0'  .. '7'
digit ::= '0'  .. '9'
nzdigit ::= '1'  .. '9'
cr ::= '\r'
lf ::= '\n'
tab ::= '\t'
stringCh ::= ANY  '-' '"'  '-' '\'  '-' cr  '-' lf
charCh ::= ANY  '-' "'"  '-' '\'  '-' cr  '-' lf
printable ::= '\u0020'  .. '\u007e'
hex ::= digit  '+' 'a'  .. 'f'  '+' 'A'  .. 'F'
TK_IDENTIFIER  ::= letter  ( letter  | digit  )*
TK_FLOAT  ::=  ( '.' digit  ( digit  )*  (  ( 'e'  | 'E'  )  ( '+'  | '-'  )? digit  ( digit  )*  )?  | digit  ( digit  )* '.'  ( digit  )*  (  ( 'e'  | 'E'  )  ( '+'  | '-'  )? digit  ( digit  )*  )?  | digit  ( digit  )*  ( 'e'  | 'E'  )  ( '+'  | '-'  )? digit  ( digit  )*  )
TK_INTEGER  ::=  ( digit  ( digit  )*  |  ( "0x"  | "0X"  ) hex  ( hex  )*  )
TK_STRING_LITERAL  ::=  ( '@'  )? '"'  ( stringCh  | '\'  ( printable  |  ( '\r'  )? '\n'  )  )* '"'  | "'"  ( charCh  | '\'  ( printable  |  ( '\r'  )? '\n'  )  )* "'"
badString  ::= '"'  ( stringCh  | '\' printable  )*  ( cr  | lf  )  | "'"  ( charCh  | '\' printable  )*  ( cr  | lf  )
TK_AND  ::= "&&"
TK_ATTR_CLOSE  ::= "/>"
TK_ATTR_OPEN  ::= "</"
TK_BASE  ::= "base"
TK_BIT_AND_EQ  ::= "&="
TK_BIT_OR_EQ  ::= "|="
TK_BIT_SHIFT_LEFT_EQ  ::= "<<="
TK_BIT_SHIFT_RIGHT_EQ  ::= ">>="
TK_BIT_XOR_EQ  ::= "^="
TK_BREAK  ::= "break"
TK_CASE  ::= "case"
TK_CATCH  ::= "catch"
TK_CLASS  ::= "class"
TK_CLONE  ::= "clone"
TK_CONST  ::= "const"
TK_CONTINUE  ::= "continue"
TK_CONSTRUCTOR  ::= "constructor"
TK_DEFAULT  ::= "default"
TK_DELETE  ::= "delete"
TK_DIVEQ  ::= "/="
TK_DO  ::= "do"
TK_DOUBLE_COLON  ::= "::"
TK_EQ  ::= "=="
TK_ELSE  ::= "else"
TK_ENUM  ::= "enum"
TK_FALSE  ::= "false"
TK___FILE__  ::= "__FILE__"
TK_FOREACH  ::= "foreach"
TK_FOR  ::= "for"
TK_FUNCTION  ::= "function"
TK___FUNCTION__  ::= "__FUNCTION__"
TK_GOTO  ::= "goto"
TK_GE  ::= ">="
TK_IF  ::= "if"
TK_IN  ::= "in"
TK_INSTANCEOF  ::= "instanceof"
TK_LE  ::= "<="
TK___LINE__  ::= "__LINE__"
TK_LOCAL  ::= "local"
TK_MINUSEQ  ::= "-="
TK_MINUSMINUS  ::= "--"
TK_MODEQ  ::= "%="
TK_MULEQ  ::= "*="
TK_NE  ::= "!="
TK_NEWSLOT  ::= "<-"
TK_NULL  ::= "null"
TK_OR  ::= "||"
TK_PLUSEQ  ::= "+="
TK_PLUSPLUS  ::= "++"
TK_RAWCALL  ::= "rawcall"
TK_RESUME  ::= "resume"
TK_RETURN  ::= "return"
TK_SHIFTL  ::= ">>"
TK_SHIFTR  ::= "<<"
TK_STATIC  ::= "static"
TK_SWITCH  ::= "switch"
TK_THIS  ::= "this"
TK_THROW  ::= "throw"
TK_3WAYSCMP  ::= "<=>"
TK_TRUE  ::= "true"
TK_TRY  ::= "try"
TK_TYPEOF  ::= "typeof"
TK_USHIFTR  ::= ">>>"
TK_VARPARAMS  ::= "..."
TK_WHILE  ::= "while"
TK_YIELD  ::= "yield"
mingodad commented 3 years ago

Looking through the compiler code it seems that there is a mistake here:

    void BitwiseOrExp()
    {
        BitwiseXorExp();
        for(;;) if(_token == _SC('|'))
        {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); ///!!!!<<< should be BitwiseOrExp ?
        }else return;
    }
mingodad commented 3 years ago

Or else the previous ones :

    void LogicalAndExp()
    {
        BitwiseOrExp();
        for(;;) switch(_token) {
        case TK_AND: {
            SQInteger first_exp = _fs->PopTarget();
            SQInteger trg = _fs->PushTarget();
            _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
            SQInteger jpos = _fs->GetCurrentPos();
            if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
            Lex(); INVOKE_EXP(&SQCompiler::LogicalAndExp); ///!!!<<< here we have full recursion could be BitwiseOrExp ?
            _fs->SnoozeOpt();
            SQInteger second_exp = _fs->PopTarget();
            if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
            _fs->SnoozeOpt();
            _fs->SetInstructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
            _es.etype = EXPR;
            break;
            }

        default:
            return;
        }
    }
mingodad commented 3 years ago

My bad they are calling different functions to generate distinct code !

mingodad commented 3 years ago

It seems that the for loops here are meaningless:

@@ -469,11 +470,11 @@ public:
         _es.etype = EXPR;
     }
     void LogicalOrExp()
     {
         LogicalAndExp();
-        for(;;) if(_token == TK_OR) {
+        if(_token == TK_OR) {
             SQInteger first_exp = _fs->PopTarget();
             SQInteger trg = _fs->PushTarget();
             _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
             SQInteger jpos = _fs->GetCurrentPos();
             if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
@@ -482,18 +483,16 @@ public:
             SQInteger second_exp = _fs->PopTarget();
             if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
             _fs->SnoozeOpt();
             _fs->SetInstructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
             _es.etype = EXPR;
-            break;
-        }else return;
+        }
     }
     void LogicalAndExp()
     {
         BitwiseOrExp();
-        for(;;) switch(_token) {
-        case TK_AND: {
+        if(_token == TK_AND) {
             SQInteger first_exp = _fs->PopTarget();
             SQInteger trg = _fs->PushTarget();
             _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
             SQInteger jpos = _fs->GetCurrentPos();
             if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
@@ -502,15 +501,10 @@ public:
             SQInteger second_exp = _fs->PopTarget();
             if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
             _fs->SnoozeOpt();
             _fs->SetInstructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
             _es.etype = EXPR;
-            break;
-            }
-
-        default:
-            return;
         }
     }
mingodad commented 3 years ago

Following the code I discovered that in literal arrays the comma separator is optional, didn't knew this before. Is this intended ?

local b = [1 2, 3 4];
print(b.len()); //Output -> 4
albertodemichelis commented 3 years ago

Yes, it was intended. In retrospect, I don't think it was a good decision but it really hasn't created any issue in my experience. FYI, this is also valid for function call parameters.

mingodad commented 3 years ago

Thank you for reply an clarify it !