diff --git a/README.md b/README.md index 2faf99d..984097e 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Variable can consist of lower-case letters, numbers, as well as `_`. ### Compound assignment -`AVGE` (+=) and `MINVE` (-=) are shorthand for incrementing or decrementing a variable: +`AVGE` (+=), `MINVE` (-=), `MVLTIPLICA` (*=) and `DIVIDE` (/=) are shorthand for updating a variable with an arithmetic operation: ![Compound assignment](snippets/compound.png) @@ -32,7 +32,7 @@ Variable can consist of lower-case letters, numbers, as well as `_`. > VIII ``` -`x AVGE III` is equivalent to `DESIGNA x VT x + III`. +`x AVGE III` is equivalent to `DESIGNA x VT x + III`; `MINVE`, `MVLTIPLICA` and `DIVIDE` expand the same way with subtraction, multiplication and division. ### Destructuring diff --git a/centvrion/lexer.py b/centvrion/lexer.py index 61f2a52..9951af8 100644 --- a/centvrion/lexer.py +++ b/centvrion/lexer.py @@ -11,6 +11,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [ "DEFINI", "DESIGNA", "DISPAR", + "DIVIDE", "DONICVM", "DVM", "CONTINVA", @@ -26,6 +27,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [ "IN", "MINVE", "MINVS", + "MVLTIPLICA", "NON", "NVLLVS", "PER", diff --git a/centvrion/parser.py b/centvrion/parser.py index 9f741f4..673ba4a 100644 --- a/centvrion/parser.py +++ b/centvrion/parser.py @@ -198,6 +198,14 @@ class Parser(): def statement_minve(tokens): return ast_nodes.Designa(tokens[0], ast_nodes.BinOp(tokens[0], tokens[2], "SYMBOL_MINUS")) + @self.pg.production('statement : id KEYWORD_MVLTIPLICA expression') + def statement_mvltiplica(tokens): + return ast_nodes.Designa(tokens[0], ast_nodes.BinOp(tokens[0], tokens[2], "SYMBOL_TIMES")) + + @self.pg.production('statement : id KEYWORD_DIVIDE expression') + def statement_divide(tokens): + return ast_nodes.Designa(tokens[0], ast_nodes.BinOp(tokens[0], tokens[2], "SYMBOL_DIVIDE")) + @self.pg.production('statement : expression') def statement_expression(tokens): return ast_nodes.ExpressionStatement(tokens[0]) diff --git a/language/main.tex b/language/main.tex index b3d2e3d..21bdc2d 100644 --- a/language/main.tex +++ b/language/main.tex @@ -33,6 +33,8 @@ \languageline{statement}{\texttt{DESIGNA} \textbf{id} \texttt{,} \textit{ids} \texttt{VT} \textit{expression}} \\ \languageline{statement}{\textbf{id} \texttt{AVGE} \textit{expression}} \\ \languageline{statement}{\textbf{id} \texttt{MINVE} \textit{expression}} \\ + \languageline{statement}{\textbf{id} \texttt{MVLTIPLICA} \textit{expression}} \\ + \languageline{statement}{\textbf{id} \texttt{DIVIDE} \textit{expression}} \\ \languageline{statement}{\texttt{DEFINI} \textbf{id} \texttt{(} \textit{optional-ids} \texttt{)} \texttt{VT} \textit{scope}} \\ \languageline{statement}{\textit{if-statement}} \\ \languageline{statement}{\texttt{DVM} \textit{expression} \texttt{FAC} \textit{scope}} \\ diff --git a/snippets/compound.cent b/snippets/compound.cent index dabc868..09c2269 100644 --- a/snippets/compound.cent +++ b/snippets/compound.cent @@ -1,3 +1,6 @@ DESIGNA x VT V x AVGE III +x MINVE II +x MVLTIPLICA IV +x DIVIDE III DIC(x) diff --git a/snippets/compound.png b/snippets/compound.png index 1c29430..09ec908 100644 Binary files a/snippets/compound.png and b/snippets/compound.png differ diff --git a/snippets/syntaxes/centvrion.sublime-syntax b/snippets/syntaxes/centvrion.sublime-syntax index 9e71361..9c7c496 100644 --- a/snippets/syntaxes/centvrion.sublime-syntax +++ b/snippets/syntaxes/centvrion.sublime-syntax @@ -78,7 +78,7 @@ contexts: scope: support.class.module.centvrion keywords: - - match: '\b(HAVD_PLVS|HAVD_MINVS|AETERNVM|ALIVD|AVGE|AVT|CAPE|CONTINVA|DEFINI|DESIGNA|DISPAR|DONICVM|DVM|ERVMPE|EST|ET|FAC|FVNCTIO|INVOCA|IN|MINVE|MINVS|NON|PER|PLVS|REDI|RELIQVVM|SI|TABVLA|TEMPTA|TVNC|VSQVE|VT|CVM)\b' + - match: '\b(HAVD_PLVS|HAVD_MINVS|AETERNVM|ALIVD|AVGE|AVT|CAPE|CONTINVA|DEFINI|DESIGNA|DISPAR|DIVIDE|DONICVM|DVM|ERVMPE|EST|ET|FAC|FVNCTIO|INVOCA|IN|MINVE|MINVS|MVLTIPLICA|NON|PER|PLVS|REDI|RELIQVVM|SI|TABVLA|TEMPTA|TVNC|VSQVE|VT|CVM)\b' scope: keyword.control.centvrion operators: diff --git a/tests.py b/tests.py index 020ad4b..d155a2e 100644 --- a/tests.py +++ b/tests.py @@ -293,6 +293,30 @@ assignment_tests = [ [Designa(ID("s"), BinOp(ID("s"), ID("i"), "SYMBOL_PLUS"))]), ExpressionStatement(ID("s"))]), ValInt(6)), + # Compound assignment — MVLTIPLICA (*=) + ("DESIGNA x VT III\nx MVLTIPLICA II\nx", + Program([], [Designa(ID("x"), Numeral("III")), + Designa(ID("x"), BinOp(ID("x"), Numeral("II"), "SYMBOL_TIMES")), + ExpressionStatement(ID("x"))]), + ValInt(6)), + # Compound assignment — DIVIDE (/=) + ("DESIGNA x VT XII\nx DIVIDE III\nx", + Program([], [Designa(ID("x"), Numeral("XII")), + Designa(ID("x"), BinOp(ID("x"), Numeral("III"), "SYMBOL_DIVIDE")), + ExpressionStatement(ID("x"))]), + ValInt(4)), + # MVLTIPLICA with complex RHS — whole expression is captured before the op + ("DESIGNA x VT II\nx MVLTIPLICA II + I\nx", + Program([], [Designa(ID("x"), Numeral("II")), + Designa(ID("x"), BinOp(ID("x"), BinOp(Numeral("II"), Numeral("I"), "SYMBOL_PLUS"), "SYMBOL_TIMES")), + ExpressionStatement(ID("x"))]), + ValInt(6)), + # DIVIDE with complex RHS + ("DESIGNA x VT XX\nx DIVIDE II + II\nx", + Program([], [Designa(ID("x"), Numeral("XX")), + Designa(ID("x"), BinOp(ID("x"), BinOp(Numeral("II"), Numeral("II"), "SYMBOL_PLUS"), "SYMBOL_DIVIDE")), + ExpressionStatement(ID("x"))]), + ValInt(5)), ] class TestAssignment(unittest.TestCase): diff --git a/vscode-extension/snippets/cent.json b/vscode-extension/snippets/cent.json index 603f458..95ba2d0 100644 --- a/vscode-extension/snippets/cent.json +++ b/vscode-extension/snippets/cent.json @@ -34,6 +34,7 @@ "CVM": { "prefix": "CVM", "body": "CVM", "description": "include module" }, "DESIGNA": { "prefix": "DESIGNA", "body": "DESIGNA", "description": "declare and assign a variable" }, "DISPAR": { "prefix": "DISPAR", "body": "DISPAR", "description": "not-equal comparison (!=)" }, + "DIVIDE": { "prefix": "DIVIDE", "body": "DIVIDE", "description": "compound division assignment (/=)" }, "ERVMPE": { "prefix": "ERVMPE", "body": "ERVMPE", "description": "break out of loop" }, "EST": { "prefix": "EST", "body": "EST", "description": "equality comparison (==)" }, "ET": { "prefix": "ET", "body": "ET", "description": "logical and" }, @@ -46,6 +47,7 @@ "INVOCA": { "prefix": "INVOCA", "body": "INVOCA", "description": "invoke / call a function" }, "MINVE": { "prefix": "MINVE", "body": "MINVE", "description": "compound subtraction assignment (-=)" }, "MINVS": { "prefix": "MINVS", "body": "MINVS", "description": "less-than comparison (<)" }, + "MVLTIPLICA": { "prefix": "MVLTIPLICA", "body": "MVLTIPLICA", "description": "compound multiplication assignment (*=)" }, "NON": { "prefix": "NON", "body": "NON", "description": "logical not" }, "NVLLVS": { "prefix": "NVLLVS", "body": "NVLLVS", "description": "null value" }, "PLVS": { "prefix": "PLVS", "body": "PLVS", "description": "greater-than comparison (>)" }, diff --git a/vscode-extension/syntaxes/cent.tmLanguage.json b/vscode-extension/syntaxes/cent.tmLanguage.json index 96d8953..ee3bcd0 100644 --- a/vscode-extension/syntaxes/cent.tmLanguage.json +++ b/vscode-extension/syntaxes/cent.tmLanguage.json @@ -45,7 +45,7 @@ "patterns": [ { "name": "keyword.control.cent", - "match": "\\b(AETERNVM|ALIVD|AVGE|AVT|CAPE|CONTINVA|CVM|DEFINI|DESIGNA|DONICVM|DVM|ERVMPE|ET|FAC|FVNCTIO|IN|INVOCA|MINVE|NON|PER|REDI|SI|TABVLA|TEMPTA|TVNC|VSQVE|VT)\\b" + "match": "\\b(AETERNVM|ALIVD|AVGE|AVT|CAPE|CONTINVA|CVM|DEFINI|DESIGNA|DIVIDE|DONICVM|DVM|ERVMPE|ET|FAC|FVNCTIO|IN|INVOCA|MINVE|MVLTIPLICA|NON|PER|REDI|SI|TABVLA|TEMPTA|TVNC|VSQVE|VT)\\b" }, { "name": "keyword.operator.comparison.cent",