@@ -634,7 +634,7 @@ func (p *Parser) evaluateProgram() (Program, error) {
634634 if err != nil {
635635 return Program {}, err
636636 }
637- statementsTemp , err := p .evaluateBlockContent (lexer .EOF , nil , ctx , SCOPE_PROGRAM )
637+ statementsTemp , err := p .evaluateBlockContent ([] lexer.TokenType { lexer . EOF } , nil , ctx , SCOPE_PROGRAM )
638638
639639 if err != nil {
640640 return Program {}, err
@@ -828,7 +828,7 @@ func (p *Parser) evaluateBlockBegin() error {
828828 return nil
829829}
830830
831- func (p * Parser ) evaluateBlockContent (terminationTokenType lexer.TokenType , callback blockCallback , ctx context , scope scope ) ([]Statement , error ) {
831+ func (p * Parser ) evaluateBlockContent (terminationTokenTypes [] lexer.TokenType , callback blockCallback , ctx context , scope scope ) ([]Statement , error ) {
832832 var err error
833833
834834 statements := []Statement {}
@@ -853,42 +853,43 @@ func (p *Parser) evaluateBlockContent(terminationTokenType lexer.TokenType, call
853853 tokenType := token .Type ()
854854 var stmt Statement
855855
856- switch tokenType {
857- case terminationTokenType :
858- // Just break on termination token.
859- loop = false
860- case lexer .NEWLINE :
861- // Ignore termination tokens as they are handled after the switch.
862- default :
863- stmt , err = p .evaluateStatement (ctx )
864- prefix := p .prefix
865-
866- if err != nil {
867- break
868- }
869- global := ctx .global ()
870-
871- switch stmt .StatementType () {
872- case STATEMENT_TYPE_VAR_DEFINITION :
873- // Store new variable.
874- err = ctx .addVariables (prefix , global , stmt .(VariableDefinition ).Variables ()... )
856+ if slices .Contains (terminationTokenTypes , tokenType ) {
857+ loop = false // Just break on termination token.
858+ } else {
859+ switch tokenType {
860+ case lexer .NEWLINE :
861+ // Ignore termination tokens as they are handled after the switch.
862+ default :
863+ stmt , err = p .evaluateStatement (ctx )
864+ prefix := p .prefix
875865
876866 if err != nil {
877- return nil , err
867+ break
878868 }
879- case STATEMENT_TYPE_VAR_DEFINITION_CALL_ASSIGNMENT :
880- // Store new variable.
881- err = ctx .addVariables (prefix , global , stmt .(VariableDefinitionCallAssignment ).Variables ()... )
869+ global := ctx .global ()
882870
883- if err != nil {
884- return nil , err
885- }
886- case STATEMENT_TYPE_FUNCTION_DEFINITION :
887- // Store new function.
888- err = ctx .addFunctions (prefix , global , stmt .(FunctionDefinition ))
871+ switch stmt .StatementType () {
872+ case STATEMENT_TYPE_VAR_DEFINITION :
873+ // Store new variable.
874+ err = ctx .addVariables (prefix , global , stmt .(VariableDefinition ).Variables ()... )
889875
890- if err != nil {
891- return nil , err
876+ if err != nil {
877+ return nil , err
878+ }
879+ case STATEMENT_TYPE_VAR_DEFINITION_CALL_ASSIGNMENT :
880+ // Store new variable.
881+ err = ctx .addVariables (prefix , global , stmt .(VariableDefinitionCallAssignment ).Variables ()... )
882+
883+ if err != nil {
884+ return nil , err
885+ }
886+ case STATEMENT_TYPE_FUNCTION_DEFINITION :
887+ // Store new function.
888+ err = ctx .addFunctions (prefix , global , stmt .(FunctionDefinition ))
889+
890+ if err != nil {
891+ return nil , err
892+ }
892893 }
893894 }
894895 }
@@ -915,7 +916,7 @@ func (p *Parser) evaluateBlockContent(terminationTokenType lexer.TokenType, call
915916 // Expect newline or termination token.
916917 if terminationToken .Type () == lexer .NEWLINE {
917918 p .eat ()
918- } else if terminationToken .Type () != terminationTokenType {
919+ } else if ! slices . Contains ( terminationTokenTypes , terminationToken .Type ()) {
919920 err = p .expectedError ("termination token" , terminationToken )
920921 break
921922 }
@@ -938,7 +939,7 @@ func (p *Parser) evaluateBlock(callback blockCallback, ctx context, scope scope)
938939 if err != nil {
939940 return nil , err
940941 }
941- statements , err := p .evaluateBlockContent (lexer .CLOSING_CURLY_BRACKET , callback , ctx , scope )
942+ statements , err := p .evaluateBlockContent ([] lexer.TokenType { lexer . CLOSING_CURLY_BRACKET } , callback , ctx , scope )
942943
943944 if err != nil {
944945 return nil , err
@@ -1617,6 +1618,119 @@ func (p *Parser) evaluateIf(ctx context) (Statement, error) {
16171618 return ifStatement , nil
16181619}
16191620
1621+ func (p * Parser ) evaluateSwitch (ctx context ) (Statement , error ) {
1622+ switchToken := p .eat ()
1623+
1624+ if switchToken .Type () != lexer .SWITCH {
1625+ return nil , p .expectedError ("switch-keyword" , switchToken )
1626+ }
1627+ var switchExpr Expression
1628+ var err error
1629+
1630+ exprToken := p .peek ()
1631+
1632+ if exprToken .Type () == lexer .OPENING_CURLY_BRACKET {
1633+ switchExpr = BooleanLiteral {true }
1634+ } else {
1635+ switchExpr , err = p .evaluateExpression (ctx )
1636+
1637+ if err != nil {
1638+ return nil , err
1639+ }
1640+ }
1641+ switchExprValueType := switchExpr .ValueType ()
1642+
1643+ if switchExprValueType .IsSlice () {
1644+ return nil , p .atError ("slices are not allowed in switch statements" , exprToken )
1645+ }
1646+ beginToken := p .eat ()
1647+
1648+ if beginToken .Type () != lexer .OPENING_CURLY_BRACKET {
1649+ return nil , p .expectedError (`{` , beginToken )
1650+ }
1651+ nextToken := p .eat ()
1652+
1653+ if nextToken .Type () != lexer .NEWLINE {
1654+ return nil , p .expectedError ("newline" , nextToken )
1655+ }
1656+ fakeIf := If {
1657+ ifBranch : IfBranch {
1658+ condition : BooleanLiteral {false }, // Use a fake if-branch that isn't entered if only a default branch has been set in switch.
1659+ body : []Statement {},
1660+ },
1661+ }
1662+ useMock := true
1663+ nextToken = p .peek ()
1664+ defaultSet := false
1665+
1666+ // While switch has not been terminated, evaluate cases.
1667+ for nextToken .Type () != lexer .CLOSING_CURLY_BRACKET {
1668+ var compareExpr Expression
1669+ var compareExprToken lexer.Token
1670+
1671+ switch nextToken .Type () {
1672+ case lexer .CASE :
1673+ p .eat () // Eat case-token.
1674+ compareExprToken = p .peek ()
1675+ exprTemp , err := p .evaluateExpression (ctx )
1676+
1677+ if err != nil {
1678+ return nil , err
1679+ }
1680+ compareExpr = exprTemp
1681+ case lexer .DEFAULT :
1682+ p .eat () // Eat default-token.
1683+ default :
1684+ return nil , p .expectedError (`"case", "default" or "}"` , nextToken )
1685+ }
1686+ colonToken := p .eat ()
1687+
1688+ if colonToken .Type () != lexer .COLON {
1689+ return nil , p .expectedError (`":"` , colonToken )
1690+ }
1691+ statements , err := p .evaluateBlockContent ([]lexer.TokenType {lexer .CASE , lexer .DEFAULT , lexer .CLOSING_CURLY_BRACKET }, nil , ctx , SCOPE_SWITCH )
1692+
1693+ if err != nil {
1694+ return nil , err
1695+ }
1696+
1697+ // Check if non-default case.
1698+ if compareExpr != nil {
1699+ compareExprValueType := compareExpr .ValueType ()
1700+
1701+ if ! switchExprValueType .Equals (compareExprValueType ) {
1702+ return nil , p .atError (fmt .Sprintf ("%s value cannot be compared with switch's %s value" , compareExprValueType .String (), switchExprValueType .String ()), compareExprToken )
1703+ }
1704+ ifBranch := IfBranch {
1705+ condition : NewComparison (switchExpr , COMPARE_OPERATOR_EQUAL , compareExpr ),
1706+ body : statements ,
1707+ }
1708+
1709+ // If fake-if has not been overwritten, overwrite it now.
1710+ if useMock {
1711+ fakeIf .ifBranch = ifBranch
1712+ useMock = false
1713+ } else {
1714+ fakeIf .elifBranches = append (fakeIf .elifBranches , ifBranch )
1715+ }
1716+ } else if ! defaultSet {
1717+ fakeIf .elseBranch = Else {
1718+ body : statements ,
1719+ }
1720+ defaultSet = true
1721+ } else {
1722+ return nil , p .atError ("multiple default cases are not allowed" , nextToken )
1723+ }
1724+ nextToken = p .peek ()
1725+ }
1726+ p .eat () // Eat "}" token.
1727+
1728+ if nextToken .Type () != lexer .CLOSING_CURLY_BRACKET {
1729+ return nil , p .expectedError (`"}"` , nextToken )
1730+ }
1731+ return fakeIf , nil
1732+ }
1733+
16201734func (p * Parser ) evaluateFor (ctx context ) (Statement , error ) {
16211735 forToken := p .eat ()
16221736
@@ -1642,7 +1756,7 @@ func (p *Parser) evaluateFor(ctx context) (Statement, error) {
16421756 nextToken = p .eat ()
16431757
16441758 if nextToken .Type () != lexer .COMMA {
1645- return nil , p .expectedError (" \" , \" " , nextToken )
1759+ return nil , p .expectedError (`","` , nextToken )
16461760 }
16471761 nextToken = p .eat ()
16481762 err = p .checkNewVariableNameToken (nextToken , ctx )
@@ -1654,7 +1768,7 @@ func (p *Parser) evaluateFor(ctx context) (Statement, error) {
16541768 nextToken = p .eat ()
16551769
16561770 if nextToken .Type () != lexer .SHORT_INIT_OPERATOR {
1657- return nil , p .expectedError (" \" := \" " , nextToken )
1771+ return nil , p .expectedError (`":="` , nextToken )
16581772 }
16591773 nextToken = p .eat ()
16601774
@@ -2033,6 +2147,8 @@ func (p *Parser) evaluateStatement(ctx context) (Statement, error) {
20332147 stmt , err = p .evaluateReturn (ctx )
20342148 case lexer .IF :
20352149 stmt , err = p .evaluateIf (ctx )
2150+ case lexer .SWITCH :
2151+ stmt , err = p .evaluateSwitch (ctx )
20362152 case lexer .FOR :
20372153 stmt , err = p .evaluateFor (ctx )
20382154 case lexer .BREAK :
0 commit comments