From eaaeb03fce0ef57fcca7b36c5d1e79f3c2e7fecd Mon Sep 17 00:00:00 2001 From: Davidson Bruno Date: Sun, 15 Apr 2018 18:12:56 -0300 Subject: [PATCH] Implemented parser - Implemented parser without handling of syntactic errors. - Updated documentation; --- README.md | 8 +- compiler/Compiler/Compiler.csproj | 5 +- compiler/Compiler/Enum/TokenCode.cs | 46 +- .../Exception/InvalidTokenException.cs | 4 +- .../Exception/TokenNotFoundException.cs | 10 + compiler/Compiler/LexicalAnalyzer.cs | 299 +++++--- compiler/Compiler/Parser.Declarations.cs | 713 ++++++++++++++++++ compiler/Compiler/Parser.Util.cs | 70 ++ compiler/Compiler/Parser.Verifications.cs | 366 +++++++++ compiler/Compiler/Program.cs | 54 +- docs/diagram/attribuition.png | Bin 5124 -> 3831 bytes docs/diagram/body.png | Bin 3420 -> 3420 bytes docs/diagram/bool.png | Bin 3273 -> 3273 bytes docs/diagram/decrement.png | Bin 1707 -> 1707 bytes docs/diagram/expression.png | Bin 14812 -> 14812 bytes docs/diagram/factor.png | Bin 10553 -> 11838 bytes docs/diagram/for.png | Bin 5763 -> 8636 bytes docs/diagram/function.png | Bin 3856 -> 3856 bytes docs/diagram/functioncall.png | Bin 0 -> 3685 bytes docs/diagram/functiondecl.png | Bin 0 -> 2445 bytes docs/diagram/if.png | Bin 3326 -> 8220 bytes docs/diagram/increment.png | Bin 1839 -> 1839 bytes docs/diagram/param.png | Bin 2811 -> 2811 bytes docs/diagram/paramcall.png | Bin 0 -> 3094 bytes docs/diagram/program.png | Bin 1934 -> 1934 bytes docs/diagram/read.png | Bin 2029 -> 2029 bytes docs/diagram/return.png | Bin 3454 -> 3454 bytes docs/diagram/rr-1.48.1593.png | Bin 687 -> 687 bytes docs/diagram/side.png | Bin 3380 -> 3380 bytes docs/diagram/statement.png | Bin 11934 -> 13185 bytes docs/diagram/term.png | Bin 4567 -> 4567 bytes docs/diagram/unaryexpr.png | Bin 4260 -> 4260 bytes docs/diagram/vardecl.png | Bin 0 -> 2655 bytes docs/diagram/write.png | Bin 2739 -> 2739 bytes docs/index.html | 138 +++- tests/source.aqua | 22 + 36 files changed, 1562 insertions(+), 173 deletions(-) create mode 100644 compiler/Compiler/Exception/TokenNotFoundException.cs create mode 100644 compiler/Compiler/Parser.Declarations.cs create mode 100644 compiler/Compiler/Parser.Util.cs create mode 100644 compiler/Compiler/Parser.Verifications.cs create mode 100644 docs/diagram/functioncall.png create mode 100644 docs/diagram/functiondecl.png create mode 100644 docs/diagram/paramcall.png create mode 100644 docs/diagram/vardecl.png create mode 100644 tests/source.aqua diff --git a/README.md b/README.md index 7ea5f95..d0db45d 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,7 @@ the_bigger: (x, y) } } -write the_bigger(5, 6.5) // Saída: 6.5 +write the_bigger(5, 6.5); // Saída: 6.5 ``` @@ -214,7 +214,7 @@ is_prime: (x) for (i: 0; i < x; i++) { - if (x % i == 0) + if (x % i = 0) { count++; @@ -228,8 +228,8 @@ is_prime: (x) return true; } -write is_prime(4) Saída: false -write is_prime(7) Saída: true +write is_prime(4); // Saída: false +write is_prime(7); // Saída: true ``` diff --git a/compiler/Compiler/Compiler.csproj b/compiler/Compiler/Compiler.csproj index 2a427fa..23fbf6e 100644 --- a/compiler/Compiler/Compiler.csproj +++ b/compiler/Compiler/Compiler.csproj @@ -61,12 +61,15 @@ + - + + + diff --git a/compiler/Compiler/Enum/TokenCode.cs b/compiler/Compiler/Enum/TokenCode.cs index e68d5c5..d377249 100644 --- a/compiler/Compiler/Enum/TokenCode.cs +++ b/compiler/Compiler/Enum/TokenCode.cs @@ -27,13 +27,13 @@ public enum TokenCode /// [Lexeme("break")] Break, /// - /// Addition operator. + /// Plus operator. /// - [Lexeme("+")] Addition, + [Lexeme("+")] Plus, /// - /// Subtraction operator. + /// Minus operator. /// - [Lexeme("-")] Subtraction, + [Lexeme("-")] Minus, /// /// Multiplication operator. /// @@ -67,21 +67,21 @@ public enum TokenCode /// [Lexeme("for")] For, /// - /// Code for opening bracket symbol. + /// Code for left bracket symbol. /// - [Lexeme("{")] OpeningBracket, + [Lexeme("{")] LeftBracket, /// - /// Code for closing bracket symbol. + /// Code for right bracket symbol. /// - [Lexeme("}")] ClosingBracket, + [Lexeme("}")] RightBracket, /// - /// Code for opening parenthesis symbol. + /// Code for left parenthesis symbol. /// - [Lexeme("(")] OpeningParenthesis, + [Lexeme("(")] LeftParenthesis, /// - /// Code for closing parenthesis symbol. + /// Code for right parenthesis symbol. /// - [Lexeme(")")] ClosingParenthesis, + [Lexeme(")")] RightParenthesis, /// /// Equal operator. /// @@ -91,17 +91,17 @@ public enum TokenCode /// [Lexeme("<=")] LessOrEqual, /// - /// Higher or equal operator. + /// Greater or equal operator. /// - [Lexeme(">=")] HigherOrEqual, + [Lexeme(">=")] GreaterOrEqual, /// /// Less operator. /// [Lexeme("<")] Less, /// - /// Higher operator. + /// Greater operator. /// - [Lexeme(">")] Higher, + [Lexeme(">")] Greater, /// /// Different operator. /// @@ -129,27 +129,23 @@ public enum TokenCode /// /// Numerical value. /// - [Lexeme("")] Number, + [Lexeme("")] Number, /// /// Textual value. /// - [Lexeme("")] Text, + [Lexeme("")] Text, /// /// Parameters separator. /// - [Lexeme(",")] Colon, + [Lexeme(",")] Comma, /// /// End of line separator. /// [Lexeme(";")] Semicolon, /// - /// Invalid token. - /// - [Lexeme("")] Invalid, - /// /// Attribuition operator. /// - [Lexeme(":")] Attribuition, + [Lexeme(":")] Colon, /// /// Code for identification lexeme. /// @@ -157,7 +153,7 @@ public enum TokenCode /// /// Code for identification lexeme. /// - [Lexeme("")] Id + [Lexeme("")] Id } public static class TokenCodeExtensions diff --git a/compiler/Compiler/Exception/InvalidTokenException.cs b/compiler/Compiler/Exception/InvalidTokenException.cs index 7808505..2c22483 100644 --- a/compiler/Compiler/Exception/InvalidTokenException.cs +++ b/compiler/Compiler/Exception/InvalidTokenException.cs @@ -3,8 +3,8 @@ [System.Serializable] public class InvalidTokenException : System.Exception { - public InvalidTokenException() : base() { } - public InvalidTokenException(string message) : base(message) { } + public InvalidTokenException() { } + public InvalidTokenException(string message) { } public InvalidTokenException(string message, System.Exception inner) : base(message, inner) { } } } diff --git a/compiler/Compiler/Exception/TokenNotFoundException.cs b/compiler/Compiler/Exception/TokenNotFoundException.cs new file mode 100644 index 0000000..cd251d6 --- /dev/null +++ b/compiler/Compiler/Exception/TokenNotFoundException.cs @@ -0,0 +1,10 @@ +namespace AquaScript.Compiler +{ + [System.Serializable] + public class TokenNotFoundException : System.Exception + { + public TokenNotFoundException() { } + public TokenNotFoundException(string message) { } + public TokenNotFoundException(string message, System.Exception inner) : base(message, inner) { } + } +} diff --git a/compiler/Compiler/LexicalAnalyzer.cs b/compiler/Compiler/LexicalAnalyzer.cs index 5327261..ed5de9a 100644 --- a/compiler/Compiler/LexicalAnalyzer.cs +++ b/compiler/Compiler/LexicalAnalyzer.cs @@ -12,8 +12,9 @@ public class LexicalAnalyzer // Private attributes private StreamReader reader; - private int line; - private int column; + private int lexicalCounter; + private int currentLine; + private int currentColumn; private int nextCharCode; private char nextChar; private int nextToken; @@ -33,14 +34,10 @@ public class LexicalAnalyzer /// Path of font file. public LexicalAnalyzer(string path) { - if (!File.Exists(path)) - { - throw new FileNotFoundException("Arquivo não encontrado."); - } - reader = new StreamReader(path); - line = 1; - column = 1; + lexicalCounter = 0; + currentLine = 1; + currentColumn = 1; nextCharCode = reader.Read(); nextChar = (char)nextCharCode; nextToken = -1; @@ -51,15 +48,28 @@ public LexicalAnalyzer(string path) // Public methods + public Token LookAhead(Token current, int index) + { + index = Tokens.IndexOf(current) + index; + + if (index >= Tokens.Count) + { + throw new TokenNotFoundException(string.Format("Attempting to read the parser to remove ambiguity after token {0} in line {1}, column {2}. No token was found.", Tokens[nextToken].Lexeme, Tokens[nextToken].Line, Tokens[nextToken].Column)); + } + + return Tokens[index]; + } + public Token Read() { nextToken++; - if (nextToken < Tokens.Count) + if (nextToken >= Tokens.Count) { - return Tokens[nextToken]; + throw new EndOfStreamException("End of parser reading."); } - return null; + + return Tokens[nextToken]; } /// @@ -67,26 +77,25 @@ public Token Read() /// public void Tokenize() { - try + while (nextCharCode != -1) { - Token token = null; - - while (true) + try { - token = GetToken(); - if (token != null) - { - Tokens.Add(token); - } + Token token = NextToken(); + Tokens.Add(token); + } + catch (InvalidTokenException e) + { + Console.WriteLine(e.Message); + } + catch (EndOfStreamException e) + { + Console.WriteLine(e.Message); } - } - catch (EndOfStreamException e) - { - Console.WriteLine(e.Message); } - Console.WriteLine("Esta foi a lista de tokens gerada:"); - WriteTokensList(); + //Console.WriteLine("Esta foi a lista de tokens gerada:"); + //WriteTokensList(); } /// @@ -94,14 +103,14 @@ public void Tokenize() /// public void WriteTokensList() { - string lexeme = "Lexema:"; - string code = "Código:"; - string line = "Linha:"; - string column = "Coluna:"; + string lexeme = "Lexeme:"; + string code = "Code:"; + string line = "Line:"; + string column = "Column:"; if (Tokens.Count == 0) { - Console.WriteLine("Nenhum token encontrado!"); + Console.WriteLine("No token found."); } else { @@ -109,19 +118,8 @@ public void WriteTokensList() foreach (Token token in Tokens) { - if (token.Code == TokenCode.Invalid) - { - Console.ForegroundColor = ConsoleColor.Red; - } - else - { - Console.ForegroundColor = ConsoleColor.White; - } - Console.WriteLine(" {0,-14} {1,-19}{2,9}{3,10}", token.Lexeme, token.Code, token.Line, token.Column); } - - Console.ForegroundColor = ConsoleColor.Gray; } } @@ -130,28 +128,28 @@ public void WriteTokensList() /// /// Get the next char in the read stream. /// - private void GetNextChar() + private void NextChar() { nextCharCode = reader.Read(); nextChar = (char)nextCharCode; - UpdateLineAndColumn(); + UpdatePosition(); } /// /// Controls the row and column change. /// - private void UpdateLineAndColumn() + private void UpdatePosition() { char nextChar = (char)nextCharCode; if (nextChar.Equals('\n')) { - column = 1; - line += 1; + currentColumn = 1; + currentLine += 1; } else { - column++; + currentColumn++; } } @@ -159,33 +157,33 @@ private void UpdateLineAndColumn() /// Get a token from the file. /// /// - private Token GetToken() + public Token NextToken() { Token token = null; String lexeme = ""; while (Char.IsWhiteSpace(nextChar)) { - GetNextChar(); + NextChar(); } - int tokenLine = line; - int tokenColumn = column; - if (nextCharCode == -1) { - throw new EndOfStreamException("Arquivo lido com sucesso!"); + throw new EndOfStreamException("End of file reading."); } + int tokenLine = currentLine; + int tokenColumn = currentColumn; + if (nextChar == '_' || Char.IsLetter(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); while (nextChar.Equals('_') || Char.IsLetterOrDigit(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); } token = new Token(lexeme, TokenCode.Id, tokenLine, tokenColumn); @@ -194,215 +192,281 @@ private Token GetToken() else if (Char.IsDigit(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); while (Char.IsDigit(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); } - token = new Token(lexeme, TokenCode.Number, tokenLine, tokenColumn); - if (nextChar.Equals('.')) { lexeme += nextChar; - GetNextChar(); + NextChar(); if (Char.IsDigit(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); while (Char.IsDigit(nextChar)) { lexeme += nextChar; - GetNextChar(); + NextChar(); } - - token.Lexeme = lexeme; } else { - token = new Token(lexeme, TokenCode.Invalid, tokenLine, tokenColumn); + lexicalCounter++; + InvalidTokenError("Invalid token \"" + lexeme + "\".", tokenLine, tokenColumn); } } + + token = new Token(lexeme, TokenCode.Number, tokenLine, tokenColumn); } else if (nextChar.Equals('"')) { lexeme += nextChar; - GetNextChar(); + NextChar(); while (nextChar != '"') { lexeme += nextChar; - GetNextChar(); + NextChar(); if (nextCharCode == -1) { - throw new EndOfStreamException("Os valores das variáveis do tipo text devem ser envolvidos com aspas."); + lexicalCounter++; + throw new EndOfStreamException("Lexical error at line " + tokenLine + ", column " + tokenColumn + ": Variables of text type must be envolved with quotation marks (\")."); } } lexeme += nextChar; token = new Token(lexeme, TokenCode.Text, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); } else if (nextChar.Equals('+')) { - token = new Token(nextChar.ToString(), TokenCode.Addition, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.Plus, tokenLine, tokenColumn); + NextChar(); if (nextChar.Equals('+')) { token.Lexeme += nextChar.ToString(); - GetNextChar(); + token.Code = TokenCode.Increment; + NextChar(); } } else if (nextChar.Equals('-')) { - token = new Token(nextChar.ToString(), TokenCode.Subtraction, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.Minus, tokenLine, tokenColumn); + NextChar(); if (nextChar.Equals('-')) { token.Lexeme += nextChar.ToString(); token.Code = TokenCode.Decrement; - GetNextChar(); + NextChar(); } } else if (nextChar.Equals('*')) { token = new Token(nextChar.ToString(), TokenCode.Multiplication, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); } else if (nextChar.Equals('/')) { - token = new Token(nextChar.ToString(), TokenCode.Division, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); if (nextChar.Equals('/')) { - token = null; - GetNextChar(); + NextChar(); - while (nextChar != '\n' || nextChar != -1) + while (nextChar != '\n' && nextCharCode != -1) { - GetNextChar(); + NextChar(); } + + token = NextToken(); } else if (nextChar.Equals('*')) { - token = null; - GetNextChar(); + NextChar(); - while (nextChar != '*') + while (true) { - GetNextChar(); + while (nextChar != '*' && nextCharCode != -1) + { + NextChar(); + } if (nextCharCode == -1) { - throw new EndOfStreamException("É necessário fechar comentários de multiplas linhas com \"*/\"."); + lexicalCounter++; + throw new EndOfStreamException("Lexical error at line " + tokenLine + ", column " + tokenColumn + ": Multiline comments must be finished with \"*/\"."); } if (nextChar.Equals('*')) { - GetNextChar(); + NextChar(); + + while (nextChar.Equals('*') && nextCharCode != -1) + { + NextChar(); + } + + if (nextCharCode == -1) + { + lexicalCounter++; + throw new EndOfStreamException("Lexical error at line " + tokenLine + ", column " + tokenColumn + ": Multiline comments must be finished with \"*/\"."); + } if (nextChar.Equals('/')) { - GetNextChar(); + NextChar(); + token = NextToken(); break; } } } } + else + { + token = new Token(nextChar.ToString(), TokenCode.Division, tokenLine, tokenColumn); + } + } + else if (nextChar.Equals('%')) + { + token = new Token(nextChar.ToString(), TokenCode.Module, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals('<')) { token = new Token(nextChar.ToString(), TokenCode.Less, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); if (nextChar.Equals('=')) { token.Lexeme += nextChar; token.Code = TokenCode.LessOrEqual; - GetNextChar(); + NextChar(); } } else if (nextChar.Equals('>')) { - token = new Token(nextChar.ToString(), TokenCode.Higher, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.Greater, tokenLine, tokenColumn); + NextChar(); if (nextChar.Equals('=')) { token.Lexeme += nextChar; - token.Code = TokenCode.HigherOrEqual; - GetNextChar(); + token.Code = TokenCode.GreaterOrEqual; + NextChar(); } } else if (nextChar.Equals('=')) { token = new Token(nextChar.ToString(), TokenCode.Equal, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); } else if (nextChar.Equals(':')) { - token = new Token(nextChar.ToString(), TokenCode.Attribuition, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.Colon, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals('!')) { token = new Token(nextChar.ToString(), TokenCode.Negation, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); if (nextChar.Equals('=')) { token.Lexeme += nextChar; token.Code = TokenCode.Different; - GetNextChar(); + NextChar(); } } else if (nextChar.Equals('(')) { - token = new Token(nextChar.ToString(), TokenCode.OpeningParenthesis, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.LeftParenthesis, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals(')')) { - token = new Token(nextChar.ToString(), TokenCode.ClosingParenthesis, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.RightParenthesis, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals('{')) { - token = new Token(nextChar.ToString(), TokenCode.OpeningBracket, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.LeftBracket, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals('}')) { - token = new Token(nextChar.ToString(), TokenCode.ClosingBracket, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.RightBracket, tokenLine, tokenColumn); + NextChar(); } else if (nextChar.Equals(';')) { token = new Token(nextChar.ToString(), TokenCode.Semicolon, tokenLine, tokenColumn); - GetNextChar(); + NextChar(); } else if (nextChar.Equals(',')) { - token = new Token(nextChar.ToString(), TokenCode.Colon, tokenLine, tokenColumn); - GetNextChar(); + token = new Token(nextChar.ToString(), TokenCode.Comma, tokenLine, tokenColumn); + NextChar(); } else { - token = new Token(nextChar.ToString(), TokenCode.Invalid, tokenLine, tokenColumn); - GetNextChar(); + lexeme += nextChar; + NextChar(); + + while (IsInvalid(nextCharCode)) + { + lexeme += nextChar; + NextChar(); + } + + lexicalCounter++; + InvalidTokenError("Invalid token \"" + lexeme + "\".", tokenLine, tokenColumn); } return token; } + private bool IsInvalid(int charactereCode) + { + char charactere = (char)charactereCode; + + if (Char.IsLetterOrDigit(charactere) + || Char.IsWhiteSpace(charactere) + || charactereCode == -1 + || charactere == '_' + || charactere == '/' + || charactere == '*' + || charactere == '+' + || charactere == '-' + || charactere == ',' + || charactere == ';' + || charactere == '(' + || charactere == ')' + || charactere == '{' + || charactere == '}' + || charactere == ':' + || charactere == '!' + || charactere == '=' + || charactere == '<' + || charactere == '>' + || charactere == '"' + ) + { + return false; + } + + return true; + } + /// /// Check if the found lexeme is a Keyword or an Identifier. /// @@ -418,5 +482,10 @@ private void LookUp(Token token) } } } + + private void InvalidTokenError(string message, int line, int column) + { + throw new InvalidTokenException(string.Format("Lexical error at line {0}, column {1}: {2}", line, column, message)); + } } } diff --git a/compiler/Compiler/Parser.Declarations.cs b/compiler/Compiler/Parser.Declarations.cs new file mode 100644 index 0000000..1556bc9 --- /dev/null +++ b/compiler/Compiler/Parser.Declarations.cs @@ -0,0 +1,713 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace AquaScript.Compiler +{ + public partial class Parser + { + private LexicalAnalyzer lexicalAnalyzer; + private Token currentToken; + + public Parser(LexicalAnalyzer lexicalAnalyzer) + { + this.lexicalAnalyzer = lexicalAnalyzer; + NextToken(); + + Program(); + } + + public void Program() + { + while (currentToken != null && IsStatement(currentToken)) + { + Statement(); + } + } + + private void Statement() + { + if (IsIf(currentToken)) + { + If(); + } + else if (IsFor(currentToken)) + { + For(); + } + else if (IsAttribuition(currentToken)) + { + Attribuition(); + } + else if (IsFunctionCall(currentToken)) + { + FunctionCall(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (IsIncrement(currentToken)) + { + Increment(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (IsDecrement(currentToken)) + { + Decrement(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (IsReturn(currentToken)) + { + Return(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (IsRead(currentToken)) + { + Read(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (IsWrite(currentToken)) + { + Write(); + + if (currentToken.Code == TokenCode.Semicolon) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else if (currentToken.Code.Equals(TokenCode.Break)) + { + NextToken(); + + if (currentToken.Code.Equals(TokenCode.Semicolon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else + { + TokenCode[] expected = new TokenCode[] + { + TokenCode.If, + TokenCode.For, + TokenCode.Id, + TokenCode.Return, + TokenCode.Read, + TokenCode.Write, + TokenCode.Break + }; + SyntaxError(currentToken, expected); + } + } + + private void If() + { + if (IsIf(currentToken)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.If); + } + + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.LeftParenthesis); + } + + Expression(); + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + + Body(); + + while (IsElseIf(currentToken)) + { + if (IsElse(currentToken)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Else); + } + + if (IsIf(currentToken)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.If); + } + + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.LeftParenthesis); + } + + Expression(); + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + + Body(); + } + + if (IsElse(currentToken)) + { + NextToken(); + Body(); + } + } + + private void For() + { + if (IsFor(currentToken)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.For); + } + + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.LeftParenthesis); + } + + VarDecl(); + + if (currentToken.Code.Equals(TokenCode.Semicolon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + + Expression(); + + if (currentToken.Code.Equals(TokenCode.Semicolon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + + if (IsAttribuition(currentToken)) + { + VarDecl(); + } + else if (IsIncrement(currentToken)) + { + Increment(); + } + else if (IsDecrement(currentToken)) + { + Decrement(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); // revisar + } + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + + Body(); + } + + private void Attribuition() + { + if (IsFunctionDecl(currentToken)) + { + FunctionDecl(); + } + else if (IsVarDecl(currentToken)) + { + VarDecl(); + + if (currentToken.Code.Equals(TokenCode.Semicolon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Semicolon); + } + } + else + { + SyntaxError(currentToken, TokenCode.Id); // Revisar + } + } + + private void VarDecl() + { + + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + + if (currentToken.Code.Equals(TokenCode.Colon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Colon); + } + + Expression(); + } + + private void FunctionDecl() + { + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + + if (currentToken.Code.Equals(TokenCode.Colon)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Colon); + } + + Function(); + } + + private void Increment() + { + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + + if (currentToken.Code.Equals(TokenCode.Increment)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Increment); + } + } + + private void Decrement() + { + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + + if (currentToken.Code.Equals(TokenCode.Decrement)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Decrement); + } + } + + private void Return() + { + if (currentToken.Code.Equals(TokenCode.Return)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Return); + } + + if (IsExpression(currentToken)) + { + Expression(); + } + } + + private void Read() + { + if (currentToken.Code.Equals(TokenCode.Read)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Read); + } + + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + } + + private void Write() + { + if (currentToken.Code.Equals(TokenCode.Write)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Write); + } + + if (IsExpression(currentToken)) + { + Expression(); + } + else // Revisar + { + TokenCode[] expected = new TokenCode[] + { + TokenCode.And + }; + SyntaxError(currentToken, expected); + } + } + + private void Function() + { + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.LeftParenthesis); + } + + if (IsParam(currentToken)) + { + Param(); + } + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + + Body(); + } + + private void Param() + { + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + + while (currentToken.Code.Equals(TokenCode.Comma)) + { + NextToken(); + + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + } + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + } + + private void Expression() + { + Side(); + + if (IsConditionalOperator(currentToken)) + { + NextToken(); + Side(); + } + + while (IsLogicalOperator(currentToken)) + { + NextToken(); + Expression(); + } + } + + private void Side() + { + Term(); + + while (currentToken.Code.Equals(TokenCode.Plus) || currentToken.Code.Equals(TokenCode.Minus)) + { + NextToken(); + Term(); + } + } + + private void Term() + { + UnaryExpr(); + + while (currentToken.Code.Equals(TokenCode.Multiplication) || currentToken.Code.Equals(TokenCode.Division) || currentToken.Code.Equals(TokenCode.Module)) + { + NextToken(); + UnaryExpr(); + } + } + + private void UnaryExpr() + { + if (currentToken.Code.Equals(TokenCode.Plus) || currentToken.Code.Equals(TokenCode.Minus)) + { + NextToken(); + } + + Factor(); + } + + private void Factor() + { + if (IsFactor(currentToken)) + { + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + Expression(); + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + } + else if (IsFunctionCall(currentToken)) + { + FunctionCall(); + } + else + { + NextToken(); + } + } + else + { + TokenCode[] expected = new TokenCode[] + { + TokenCode.True, + TokenCode.False, + TokenCode.Number, + TokenCode.Text, + TokenCode.Id, + TokenCode.Null, + TokenCode.LeftParenthesis + }; + SyntaxError(currentToken, expected); + } + } + + private void ParamCall() + { + if (IsParamCall(currentToken)) + { + Expression(); + + while (currentToken.Code.Equals(TokenCode.Comma)) + { + NextToken(); + + if (IsParamCall(currentToken)) + { + Expression(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); // revisar + } + } + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + } + + private void FunctionCall() + { + if (currentToken.Code.Equals(TokenCode.Id)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.Id); + } + + if (currentToken.Code.Equals(TokenCode.LeftParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.LeftParenthesis); + } + + if (IsParamCall(currentToken)) + { + ParamCall(); + } + + if (currentToken.Code.Equals(TokenCode.RightParenthesis)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightParenthesis); + } + } + + private void Body() + { + if (currentToken.Code.Equals(TokenCode.LeftBracket)) + { + NextToken(); + + while (IsStatement(currentToken)) + { + Statement(); + } + + if (currentToken.Code.Equals(TokenCode.RightBracket)) + { + NextToken(); + } + else + { + SyntaxError(currentToken, TokenCode.RightBracket); + } + } + else + { + SyntaxError(currentToken, TokenCode.LeftBracket); + } + } + } +} \ No newline at end of file diff --git a/compiler/Compiler/Parser.Util.cs b/compiler/Compiler/Parser.Util.cs new file mode 100644 index 0000000..d3c0285 --- /dev/null +++ b/compiler/Compiler/Parser.Util.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AquaScript.Compiler +{ + public partial class Parser + { + private void NextToken() + { + try + { + currentToken = lexicalAnalyzer.Read(); + } + catch (EndOfStreamException e) + { + Console.WriteLine(e.Message); + } + } + + public Token LookAhead(Token current, int index) + { + try + { + return lexicalAnalyzer.LookAhead(current, index); + } + catch (TokenNotFoundException e) + { + Console.WriteLine(e.Message); + return currentToken; + } + } + + public void SyntaxError(Token token, TokenCode expected) + { + throw new SyntaxErrorException(string.Format("Syntax error at line {0}, column {1}: The token {2} provided is invalid. Expected: {3}", token.Line, token.Column, token.Lexeme, expected.GetLexeme())); + } + + public void SyntaxError(Token token, TokenCode[] expected) + { + string expectedText = ""; + + if (expected.Length < 2) + { + expectedText += expected[0].GetLexeme(); + } + else + { + expectedText += expected[0].GetLexeme(); + + for (int i = 1; i < expected.Length; ++i) + { + if (i == expected.Length - 1) + { + expectedText = " ou " + expected[i].GetLexeme(); + } + else + { + expectedText = ", " + expected[i].GetLexeme(); + } + } + } + + throw new SyntaxErrorException(string.Format("Syntax error at line {0}, column {1}: The token {2} provided is invalid. Expected: {3}", token.Line, token.Column, token.Lexeme, expectedText)); + } + } +} diff --git a/compiler/Compiler/Parser.Verifications.cs b/compiler/Compiler/Parser.Verifications.cs new file mode 100644 index 0000000..b10869b --- /dev/null +++ b/compiler/Compiler/Parser.Verifications.cs @@ -0,0 +1,366 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AquaScript.Compiler +{ + public partial class Parser + { + private bool IsStatement(Token token) + { + switch (token.Code) + { + case TokenCode.If: + case TokenCode.For: + case TokenCode.Id: + case TokenCode.Return: + case TokenCode.Write: + case TokenCode.Read: + case TokenCode.Break: + return true; + default: + return false; + } + } + + private bool IsIf(Token token) + { + switch (token.Code) + { + case TokenCode.If: + return true; + default: + return false; + } + } + + private bool IsElse(Token token) + { + switch (token.Code) + { + case TokenCode.Else: + return true; + default: + return false; + } + } + + private bool IsElseIf(Token token) + { + if (currentToken.Code.Equals(TokenCode.Else)) + { + if (LookAhead(token, 1).Code.Equals(TokenCode.If)) + { + return true; + } + } + + return false; + } + + private bool IsFor(Token token) + { + switch (token.Code) + { + case TokenCode.For: + return true; + default: + return false; + } + } + + private bool IsAttribuition(Token token) + { + if (token.Code.Equals(TokenCode.Id)) + { + if (LookAhead(token, 1).Code.Equals(TokenCode.Colon)) + { + return true; + } + } + + return false; + } + + private bool IsIncrement(Token token) + { + if (token.Code.Equals(TokenCode.Id)) + { + if (LookAhead(token, 1).Code.Equals(TokenCode.Increment)) + { + return true; + } + } + + return false; + } + + private bool IsDecrement(Token token) + { + if (token.Code.Equals(TokenCode.Id)) + { + if (LookAhead(token, 1).Code.Equals(TokenCode.Decrement)) + { + return true; + } + } + + return false; + } + + private bool IsReturn(Token token) + { + switch (token.Code) + { + case TokenCode.Return: + return true; + default: + return false; + } + } + + private bool IsRead(Token token) + { + switch (token.Code) + { + case TokenCode.Read: + return true; + default: + return false; + } + } + + private bool IsWrite(Token token) + { + switch (token.Code) + { + case TokenCode.Write: + return true; + default: + return false; + } + } + + private bool IsExpression(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.Plus: + case TokenCode.Minus: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsBodyFirst(Token token) + { + switch (token.Code) + { + case TokenCode.LeftBracket: + return true; + default: + return false; + } + } + + private bool IsVarDecl(Token token) + { + if (IsExpression(LookAhead(token, 2))) + { + return true; + } + + return false; + } + + private bool IsFunctionDecl(Token token) + { + if (IsFunction(LookAhead(token, 2))) + { + return true; + } + + return false; + } + + private bool IsFunction(Token token) + { + if (token.Code.Equals(TokenCode.LeftParenthesis)) + { + if (LookAhead(token, 2).Code.Equals(TokenCode.RightParenthesis) || LookAhead(token, 2).Code.Equals(TokenCode.Comma) || LookAhead(token, 3).Code.Equals(TokenCode.LeftBracket)) + { + return true; + } + } + + return false; + } + + private bool IsSide(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.Plus: + case TokenCode.Minus: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsParam(Token token) + { + switch(token.Code) + { + case TokenCode.Id: + return true; + default: + return false; + } + } + + private bool IsParamCall(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.Plus: + case TokenCode.Minus: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsTerm(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.Plus: + case TokenCode.Minus: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsUnaryExprFirst(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.Plus: + case TokenCode.Minus: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsFactor(Token token) + { + switch (token.Code) + { + case TokenCode.Id: + case TokenCode.True: + case TokenCode.False: + case TokenCode.Number: + case TokenCode.Text: + case TokenCode.Null: + case TokenCode.LeftParenthesis: + return true; + default: + return false; + } + } + + private bool IsBool(Token token) + { + switch (token.Code) + { + case TokenCode.True: + case TokenCode.False: + return true; + default: + return false; + } + } + + private bool IsFunctionCall(Token token) + { + if (token.Code.Equals(TokenCode.Id)) + { + if (LookAhead(token, 1).Code.Equals(TokenCode.LeftParenthesis)) + { + return true; + } + } + + return false; + } + + private bool IsConditionalOperator(Token token) + { + switch(token.Code) + { + case TokenCode.Equal: + case TokenCode.Different: + case TokenCode.Less: + case TokenCode.Greater: + case TokenCode.LessOrEqual: + case TokenCode.GreaterOrEqual: + return true; + default: + return false; + } + } + + private bool IsLogicalOperator(Token token) + { + switch(token.Code) + { + case TokenCode.And: + case TokenCode.Or: + return true; + default: + return false; + } + } + } +} diff --git a/compiler/Compiler/Program.cs b/compiler/Compiler/Program.cs index 00056b3..c9e6bc0 100644 --- a/compiler/Compiler/Program.cs +++ b/compiler/Compiler/Program.cs @@ -7,14 +7,64 @@ class Program { static void Main(string[] args) { + string source = ""; + + for (int i = 0; i < args.Length; ++i) + { + if (args[i].ToLower().EndsWith(".aqua")) + { + source = args[i]; + } + } + + Header(); + try { - LexicalAnalyzer lexicalAnalyzer = new LexicalAnalyzer("source.aqua"); + LexicalAnalyzer lexicalAnalyzer = new LexicalAnalyzer(source); + + Console.WriteLine("Reading from file " + Path.GetFullPath(source)); + + Parser parser = new Parser(lexicalAnalyzer); + } + catch(FileNotFoundException) + { + Console.WriteLine("File " + Path.GetFullPath(source) + " not found."); + } + catch(DirectoryNotFoundException) + { + Console.WriteLine("Part of the path " + Path.GetFullPath(source) + " was not found."); } - catch(FileNotFoundException e) + catch(ArgumentNullException) + { + Console.WriteLine("Value can't be null. Enter a valid filename."); + } + catch(ArgumentException e) + { + Console.WriteLine("Filename can not be empty. Enter a valid filename."); + } + } + + static void GetNextToken(LexicalAnalyzer lexicalAnalyzer) + { + try + { + + } + catch (InvalidTokenException e) { Console.WriteLine(e.Message); } + catch (EndOfStreamException e) + { + Console.WriteLine(e.Message); + } + } + + static void Header() + { + Console.WriteLine("AquaScript Compiler v0.1.0"); + Console.WriteLine("Copyright (c) 2018"); } } } diff --git a/docs/diagram/attribuition.png b/docs/diagram/attribuition.png index 86e84daae797e172b0438b75adcb3016e112e9eb..cf00eb9e5578be9486bcff30f8889d8a90d13a2b 100644 GIT binary patch literal 3831 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 literal 5124 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 B%3uHh diff --git a/docs/diagram/body.png b/docs/diagram/body.png index 7a883ef18c2025757b64639f6fd84102609158a7..512291bc8b668b80a4bdbefd958a7885d167bada 100644 GIT binary patch delta 19 acmca3bw_G~9S6TC8~?M-wZpc~WwM9S6TCn?UyNf@2%qnt1?0=LWX` delta 19 bcmX>pc~WwM9S0A$3F~|5hbK0=HS+)fMJ@*< diff --git a/docs/diagram/decrement.png b/docs/diagram/decrement.png index 232f9c33973c0a646e1a418a574dde3fcc850ae6..36cb28a83804a58401484307e2ccaa41b568b48e 100644 GIT binary patch delta 19 acmZ3@yP9``9S6TCn?UyNf@2%qQrQ4I)doKR delta 19 bcmZ3@yP9``9S0A$3F~|5hbK0=rLqA4KO6?E diff --git a/docs/diagram/expression.png b/docs/diagram/expression.png index 24b59b07a606e9f8f110616955984eeb03823c4d..e851adc6e66d93f28a63f3a0fb775f357150a55a 100644 GIT binary patch delta 19 bcmcape5ZJV9S6TCn?UyNf@2%qrda|2P}&F4 delta 19 bcmcape5ZJV9S0A$3F~|5hbK0=O|t|5R3QjH diff --git a/docs/diagram/factor.png b/docs/diagram/factor.png index 2d78b6f27d62e035ce41faf9e7be804845b6f24f..76ba9f7ea3e0946b501ae523d9be3ff8d9d565ed 100644 GIT binary patch literal 11838 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°)}XhQ-xQ~Cd<8=um{FqE9`X;HrWKD8j8|IH~~ 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 literal 10553 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 literal 5763 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 literal 3326 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 diff --git a/docs/diagram/increment.png b/docs/diagram/increment.png index 4cc4e992a0f62174a962118f0454d527c98624d7..0106d295057ba72a5496ee80e721f87177cdf09e 100644 GIT binary patch delta 19 bcmZ3_x1Mi;9S6TCn?UyNf@2%qUa|oIJ&y*> delta 19 acmZ3_x1Mi;9S0A$30s-ahN6vbFWCS(1O_qy diff --git a/docs/diagram/param.png b/docs/diagram/param.png index fac0853f44c9e994e8b3b1da8967883bbf206ac1..367d0789552f06d812bbac9331fa70dd05efc588 100644 GIT binary patch delta 19 bcmew@`df5@9S6TCn?UyNf@2%qwsHXgNXZ97 delta 19 acmew@`df5@9S0A$30s-ahN6vbTe$#5J_e`& diff --git a/docs/diagram/paramcall.png b/docs/diagram/paramcall.png new file mode 100644 index 0000000000000000000000000000000000000000..a00e7053007f1e016de4d254c685a681b88addef GIT binary patch literal 3094 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 diff --git a/docs/diagram/return.png b/docs/diagram/return.png index 5f45a56b5646645fb65034a6ed91231de262c49f..5bc614c9853c05d364d964e40fb8406285ece4f1 100644 GIT binary patch delta 19 acmew-^-pSo9S6TCn?UyNf@2%qEO-G(=myyU delta 19 acmew-^-pSo9S0A$30s-ahN6vb7Q6sOT?Re? diff --git a/docs/diagram/rr-1.48.1593.png b/docs/diagram/rr-1.48.1593.png index 7498c45818ce9fb3ce902abd0cdc806f6a95717c..065e400ac2e70433ceae3b66fd2ac219bb94d281 100644 GIT binary patch delta 19 acmZ3_x}J4{9S6TCn?UyNf@2%qGMNB7Sq3)% delta 19 acmZ3_x}J4{9S0A$30s-ahN6vbnM?pT&IOzR diff --git a/docs/diagram/side.png b/docs/diagram/side.png index 24cbccf7bb542beed5b75e7fcc3629a6ac6c7dc7..f91f69598ea8b67f782c9b35c9381103df90f317 100644 GIT binary patch delta 19 bcmdlYwMA-z9S6TCn?UyNf@2%q-thncKkEki delta 19 acmdlYwMA-z9S0A$30s-ahN6vb?|1+_U2>tZ& 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 P(7?$`DM^-!8@~B}u5os? literal 11934 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 LR*@-{dhYu_GJM>W diff --git a/docs/diagram/term.png b/docs/diagram/term.png index ff176a21f785e71ed621564078497094cce48829..eaea241f129cf7d4ac3d943dae45fb666557fe43 100644 GIT binary patch delta 19 bcmcbvd|i2h9S6TCn?UyNf@2%qCJF)oMN|g* delta 19 acmcbvd|i2h9S0A$30s-ahN6vb69oZ5$p&8l diff --git a/docs/diagram/unaryexpr.png b/docs/diagram/unaryexpr.png index 9629b5a1cf0525009c3eb00be09fc1f9a9994f9a..3a329e829d5238e1477eb193bc886d57569fa90f 100644 GIT binary patch delta 19 acmZ3YxI}S+9S6TCn?UyNf@2%q;sgLaeFj_r delta 19 acmZ3YxI}S+9S0A$30s-ahN6vbaRLB2@&&;F diff --git a/docs/diagram/vardecl.png b/docs/diagram/vardecl.png new file mode 100644 index 0000000000000000000000000000000000000000..63f485f50c4066a12d0acd113b46312118fc3a32 GIT binary patch literal 2655 zcmV-l3ZV6gP)Jk5No?|#sB~c0ZBwbRCt{2oqbGI=N-pC&%MY61hp^t zQYt|vmE`IYo=iKL< zBe=z|rjjZJ79m(BAu^C-1dK_^1tDp*baVR*KACMFTIscz zDgRl~W4nI!%#YPbKkxX{{&)DpYkxZiysPC%YtW*IH*zwK1u;<(@73iiI%|4fo%}CZ+Q$-G|zG!-PJ%7`8vtSo*!J_&c)K+^Kr4>@|0ib6>n5 zQv5kPgSATLR-+F!^@a(3bTMqCN$mXjPwt7+s@^kCrV<@#jCR;Luo;X>we*Gw zeKa@h+B8z4Ovc5@D>d^g$t&ZCiZUW0zBhwXC333ShZ=gr%ndX*Y=p#`anEg9mnCiW z5`iRb^wRCQ8;OO|CZIqcyDQFy=n1(hsxE<@Z@3i#S$rmiH-gH^-!S33-0%K^tWoTgX4`igngf#W{NX#wK%gXE~KA+b49T zG?DA-!ISR(z3bTjbc50#EqM2lC!ts={Rh#JkmhRlb=0e=+L}53Ti(_}tQ(ysO7akgHox`Y z4BfpzBEV9%HkG&??AxB&h>LbA?-IVSlC zz#+LJ@aQ=}q5EMS5Gw>r0@_y)9dyCfv8)O%Llh9ym#B*L5jZ;NJwxTjQYxoxeX5rU zW9%;E(8iX@M)OL)(|oh4m&xwE>qvOIl>M&l*6|VDS1b_x=?VzHe;)*{ffm;y@yNa?{tlveMczRSV!G@*Z$sO{#pbefn=Y$0w93D zkHt(mV%q0F)kj#OI9ZH%JT!>Y|5yaS6xe0 zVL1sm9erOR%}u^_DaOovBwZ$c+ik>6L9!%5!f}J(hu#wSi>u9^mVEZO{l4mnT!x;| zT1D^#bU#RCXBeASYbjfs>OD`D zJ?T<#;l(U{G|9L~7Db%s;DE0q{KdnB3FDt2eRR{fx;!;;Y-G$aMu3knRf?f66@MV1 zs(q-SR~v4j<$!Y$%@_X*7&t#TJgRlwa~Fmc&8K!BO6v_XH_+U$Hw3o!PruT-EFEW@ zE5js=;b17(d}{ZhwB9gt1I-P4vV-oCQTsPNXD|ETSs{APUS?#(4uF7B0RzG2RI?8? z^oE%m=<-abu~Aw5$Jal-qE)@u{?f&@(QyNCLts-PuUdVmr8i9Iql;k^+U)fopBTE> za_XY$wOUSH5^|wcF?UvZZ-N)Q*W5iM;F7s0ro4y*Ej8`wT*oCg?a<+ zXJ1@l$1WRJhHp4GNG=N_UcSwnIZF4Tw%#zIk8V%?Z)xY`=rzZa#m{{xn{D2fwauPp z+aM*+eaMw-H{3U0N@}NG$vR5)p_Se+p^dI@ulxAF_5;>5O3HTI8rG)YE}kt(Ly4DR zz1+~j$@vXtgrZ>Ru?bz88Odopa4HLTP{`NWmODda<5n{i|WQ>e58Ocal z!ir@vEW0BrpyMxG8e!nVFzwx6Gcsytbksg^4(Q~naPU)Gmvgmj#j3}Z@ z*C_nB8_jO*nPDHA={W`v!JHI-B;un562 z3CjXGM!*FrxgaF1wl2EV)))xB`p`q~&5>4%TJr^I;Mj?F-qoVk{{bCCD*iM%eM0~M N002ovPDHLkV1m+#Hjn@S literal 0 HcmV?d00001 diff --git a/docs/diagram/write.png b/docs/diagram/write.png index 9742ca4ba1b6426b0269b4bc7eadda8e1c030439..e40dbcf8a542d6127dacadd35f906ce0320d5252 100644 GIT binary patch delta 19 acmdlix> +

program:

@@ -182,15 +182,16 @@

no references


statement:

- + - - - - - + + + + + +

@@ -198,7 +199,7 @@ ::= if | for | attribuition - | ( increment | decrement | return | read | write | 'break' ) ';' + | ( functioncall | increment | decrement | return | read | write | 'break' ) ';'

@@ -213,13 +214,14 @@


if:

- - - + + + +

-

if       ::= 'if' '(' expression ')' body
+
if       ::= 'if' '(' expression ')' body ( 'else' 'if' '(' expression ')' body )* ( 'else' body )?

@@ -232,15 +234,17 @@


for:

- + - + + +

-

for      ::= 'for' '(' attribuition? ';' expression? ';' attribuition? ')' body
+
for      ::= 'for' '(' attribuition? ';' expression? ';' ( attribuition | increment | decrement )? ')' body

@@ -253,14 +257,15 @@


attribuition:

- - - + + +

attribuition
-         ::= 'id' ':' ( function | expression ';' )
+ ::= functiondecl + | vardecl ';'

@@ -274,6 +279,43 @@ +


functiondecl:

+ + + +

+ +

functiondecl
+         ::= 'id' ':' function
+ +

+ +

referenced by: + +

+ +


vardecl:

+ + + +

+ +

vardecl  ::= 'id' ':' expression
+ +

+ +

referenced by: + +

+


increment:

@@ -288,6 +330,8 @@ @@ -306,6 +350,8 @@ @@ -378,7 +424,7 @@ @@ -398,16 +444,18 @@ @@ -507,9 +555,10 @@


factor:

- + - + +

@@ -518,6 +567,7 @@ | 'text' | 'id' | 'null' + | functioncall | '(' expression ')'

@@ -548,6 +598,46 @@ +


functioncall:

+ + + +

+ +

functioncall
+         ::= 'id' '(' paramcall? ')'
+ +

+ +

referenced by: + +

+ +


paramcall:

+ + + +

+ +

+ +

+ +

referenced by: + +

+



diff --git a/tests/source.aqua b/tests/source.aqua new file mode 100644 index 0000000..ad701ff --- /dev/null +++ b/tests/source.aqua @@ -0,0 +1,22 @@ +is_prime: (x) +{ + count: 0; + + for (i: 0; i < x; i++) + { + if (x % i = 0) + { + count++; + + if (count > 2) + { + return false; + } + } + } + + return true; +} + +write is_prime(4); // Saída: false +write is_prime(7); // Saída: true \ No newline at end of file