Ver código fonte

Implemented While and For loops parser. Added global variables to IVProgParser to indicate command parsing scopes

Lucas de Souza 5 anos atrás
pai
commit
5f1b0394ba

+ 14 - 0
.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Launch Program",
+            "program": "${workspaceFolder}/js/main.js"
+        }
+    ]
+}

+ 2 - 0
.vscode/settings.json

@@ -0,0 +1,2 @@
+{
+}

+ 0 - 7
js/ast/ASA.js

@@ -1,10 +1,3 @@
-export class ASA {
-
-  constructor() {
-    this.nos = [];
-  }
-}
-
 /*
   Raiz(ASA)
     |

+ 0 - 8
js/ast/NoDeclaracao.js

@@ -1,8 +0,0 @@
-export class NoDeclaracao {
-
-  constructor(id, tipo, valor = null) {
-    this.id = id;
-    this.tipo = tipo;
-    this.valor = valor;
-  }
-}

+ 0 - 10
js/ast/NoGlobal.js

@@ -1,10 +0,0 @@
-export class NoGlobal {
-
-  constructor() {
-    this.declaracoes = [];
-  }
-
-  addDeclaracao(decl) {
-    this.declaracoes.push(decl);
-  }
-}

+ 2 - 2
js/ast/SyntaxError.js

@@ -6,11 +6,11 @@ export class SyntaxError extends Error {
   }
 
   static getErrorString (symbol, token) {
-    return `Syntax error: Expecting '${symbol}' but found ${token.text} at line:${token.line}, column:${token.column}`;
+    return `Syntax error: Expecting '${symbol}' but found '${token.text}' at line:${token.line}, column:${token.column}`;
   }
 
   constructor (...msg) {
     super(...msg);
-    //Error.captureStackTrace(this, SyntaxError);
+    Error.captureStackTrace(this, SyntaxError);
   }
 }

+ 11 - 0
js/ast/commands/arrayDeclaration.js

@@ -0,0 +1,11 @@
+import { Declaration } from './declaration';
+
+export class ArrayDeclaration extends Declaration {
+
+  constructor (id, subtype, lines, columns, initial, isConst)   {
+    super(id, 'array', initial, isConst);
+    this.subtype = subtype;
+    this.lines = lines;
+    this.columns = columns;
+  }
+}

+ 9 - 0
js/ast/commands/declaration.js

@@ -0,0 +1,9 @@
+export class Declaration {
+  
+  constructor (id, type, initial, isConst) {
+    this.id = id;
+    this.type = type;
+    this.initial = initial;
+    this.isConst = isConst;
+  }
+}

+ 12 - 0
js/ast/commands/for.js

@@ -0,0 +1,12 @@
+export class For {
+  constructor (attribution, condition, increment, commandBlock) {
+    this.attribution = attribution;
+    this.condition = condition;
+    this.increment = increment;
+    this.commandBlock = commandBlock;
+  }
+
+  get commands () {
+    return this.commandBlock.commands;
+  }
+}

+ 5 - 1
js/ast/commands/index.js

@@ -1,7 +1,11 @@
 import { Break } from './break';
 import { Return } from './return';
 import { Atribution } from './atribution';
+import { Declaration } from './declaration';
+import { ArrayDeclaration } from './arrayDeclaration';
+import { While } from './while';
+import { For } from './for';
 
 export {
-  Break, Return, Atribution
+  Break, Return, Atribution, Declaration, ArrayDeclaration, While, For
 };

+ 10 - 0
js/ast/commands/while.js

@@ -0,0 +1,10 @@
+export class While {
+  constructor (expression, commandBlock) {
+    this.expression = expression;
+    this.commandBlock = commandBlock;
+  }
+
+  get commands () {
+    return this.commandBlock.commands;
+  }
+}

+ 77 - 0
js/ast/expressions/arrayLiteral.js

@@ -0,0 +1,77 @@
+import { Literal } from './literal';
+export class ArrayLiteral extends Literal {
+  
+  constructor(value) {
+    super('array');
+    this.value = value;
+  }
+
+  get subtype () {
+    let element = this.value[0];
+    if (element instanceof ArrayLiteral) {
+      return element.value[0].type;
+    } else {
+      return element.type;
+    }
+  }
+
+  get lines () {
+    return this.value.length;
+  }
+
+  get columns () {
+    let element = this.value[0];
+    if (!(element instanceof ArrayLiteral)){
+      return null;
+    } else {
+      return element.value[0].value.length;
+    }
+  }
+
+  get isValid () {
+    return this.validateType() && this.validateSize();
+  }
+
+  validateType () {
+    let valid = true;
+    if(this.columns !== null) {
+      const len = this.columns;
+      const len2 = this.lines;
+      for (let i = len - 1; i >= 0; i--) {
+        for (let j = len2 - 1; j >= 0; j--) {
+          if(this.value[i].value[j].type !== this.subtype) {
+            valid = false;
+            break;
+          }
+        }
+      }
+    } else {
+      const len = this.lines;
+      for (var i = len - 1; i >= 0; i--) {
+        if(this.value[i].type !== this.subtype) {
+          valid = false;
+          break;
+        }
+      }
+    }
+    return valid;
+  }
+
+  validateSize () {
+    let valid = true;
+    if(this.columns !== null) {
+      const equalityTest = data.value.map(v => v.length)
+      .reduce((old, next) => {
+        if (old === null) {
+          return next;
+        } else if (old === next) {
+          return old
+        } else {
+          return -1;
+        }
+      }, null);
+      valid = equalityTest !== -1;
+    }
+    return valid;
+  }
+}

+ 8 - 0
js/ast/expressions/boolLiteral.js

@@ -0,0 +1,8 @@
+import { Literal } from './literal';
+export class BoolLiteral extends Literal {
+  
+  constructor(value) {
+    super('bool');
+    this.value = value;
+  }
+}

+ 13 - 1
js/ast/expressions/index.js

@@ -1,7 +1,19 @@
 import { ArrayAccess } from './arrayAccess';
 import { FunctionCall } from './functionCall';
+import { IntLiteral } from './intLiteral';
+import { RealLiteral } from './realLiteral';
+import { BoolLiteral } from './boolLiteral';
+import { StringLiteral } from './stringLiteral';
+import { ArrayLiteral } from './arrayLiteral';
+import { VariableLiteral } from './variableLiteral';
 
 export {
 	ArrayAccess,
-	FunctionCall
+	FunctionCall,
+  IntLiteral,
+  RealLiteral,
+  BoolLiteral,
+  StringLiteral,
+  ArrayLiteral,
+  VariableLiteral
 };

+ 8 - 0
js/ast/expressions/intLiteral.js

@@ -0,0 +1,8 @@
+import { Literal } from './literal';
+export class IntLiteral extends Literal {
+  
+  constructor(value) {
+    super('int');
+    this.value = value;
+  }
+}

+ 6 - 0
js/ast/expressions/literal.js

@@ -0,0 +1,6 @@
+export class Literal {
+  
+  constructor (type) {
+    this.type = type;
+  }
+}

+ 8 - 0
js/ast/expressions/realLiteral.js

@@ -0,0 +1,8 @@
+import { Literal } from './literal';
+export class RealLiteral extends Literal {
+  
+  constructor(value) {
+    super('real');
+    this.value = value;
+  }
+}

+ 8 - 0
js/ast/expressions/stringLiteral.js

@@ -0,0 +1,8 @@
+import { Literal } from './literal';
+export class StringLiteral extends Literal {
+  
+  constructor(value) {
+    super('string');
+    this.value = value;
+  }
+}

+ 8 - 0
js/ast/expressions/variableLiteral.js

@@ -0,0 +1,8 @@
+import { Literal } from './literal';
+export class VariableLiteral extends Literal {
+  
+  constructor(value) {
+    super('variable');
+    this.value = value;
+  }
+}

+ 159 - 85
js/ast/ivprogParser.js

@@ -1,10 +1,23 @@
 import { CommonTokenStream, InputStream } from 'antlr4/index';
-import { ArrayAccess, FunctionCall} from './expressions/';
-import { Return, Break, Atribution } from './commands/';
+import * as Expressions from './expressions/';
+import * as Commands from './commands/';
 import { SyntaxError } from './SyntaxError';
 
 export class IVProgParser {
 
+  static get BASE () {
+    return 0;
+  }
+  static get FUNCTION () {
+    return 1;
+  }
+  static get COMMAND () {
+    return 2;
+  }
+  static get LOOP () {
+    return 4;
+  }
+
   constructor (input, lexerClass) {
     this.lexerClass = lexerClass;
     this.lexer = new lexerClass(new InputStream(input));
@@ -17,6 +30,7 @@ export class IVProgParser {
       this.lexerClass.RK_STRING
     ];
     this.functionTypes = this.variableTypes.concat(this.lexerClass.RK_VOID);
+    this.parsingArrayDimension = 0;
   }
 
   parseTree () {
@@ -50,7 +64,7 @@ export class IVProgParser {
         if (token.type === this.lexerClass.RK_CONST || token.type === this.lexerClass.ID) {
           globalVars = globalVars.concat(this.parseGlobalVariables());
         } else if (token.type === this.lexerClass.RK_FUNCTION) {
-          functions = functions.concat(this.parseFunctions());
+          functions = functions.concat(this.parseFunction());
         } else {
           break;
         }
@@ -150,22 +164,11 @@ export class IVProgParser {
   }
 
   parseGlobalVariables () {
-    let vars = [];
-    while(true) {
-      const decl = this.parseMaybeConst();
-      const eosToken = this.getToken();
-      if (decl !== null) {
-        this.checkEOS();
-      }
-
-      if (decl === null) {
-        break;
-      } else {
-        vars = vars.concat(decl);
-        this.pos++;
-      }
-    }
-    return vars;
+    const decl = this.parseMaybeConst();
+    const eosToken = this.getToken();
+    this.checkEOS();
+    this.pos++;
+    return decl;
   }
 
   /*
@@ -183,7 +186,7 @@ export class IVProgParser {
       this.pos++;
       return this.parseDeclararion(constToken);
     } else {
-      return null;
+      throw SyntaxError.createError(this.lexer.literalNames[this.lexerClass.RK_CONST] + ' or ' + this.getTypesAsString(), constToken);
     }
 
   }
@@ -221,30 +224,22 @@ export class IVProgParser {
       this.pos++;
       initial = this.parseExpressionOR();
     }
-    
+    let declaration = null;
+    if (dim1 !== null) {
+      declaration = new Commands.ArrayDeclaration(idString,
+        typeString, dim1, dim2, initial, isConst);
+    } else {
+      declaration = new Commands.Declaration(idString, typeString, initial, isConst);
+    }
     const commaToken = this.getToken();
     if(commaToken.type === this.lexerClass.COMMA) {
       console.log("comma found");
       this.pos++;
       this.consumeNewLines();
-      return [{
-        isConst: isConst,
-        tipo: typeString,
-        id: idString,
-        lines: dim1,
-        columns: dim2,
-        initial: initial
-      }]
+      return [declaration]
       .concat(this.parseDeclararion(typeString, isConst));
     } else {
-       return [{
-        isConst: isConst,
-        tipo: typeString,
-        id: idString,
-        lines: dim1,
-        columns: dim2,
-        initial: initial
-      }]
+       return [declaration]
     }
   }
 
@@ -294,32 +289,53 @@ export class IVProgParser {
     } else {
       val = parseInt(text);
     }
-    return {type: 'int', value: val};
+    return new Expressions.IntLiteral(val);
   }
 
   getRealLiteral (token) {
-    return {type: 'real', value: parseFloat(token.text)};
+    return new Expressions.RealLiteral(parseFloat(token.text));
   }
 
   getStringLiteral (token) {
     const text = token.text;
-    let valor = text.replace("\\b", "\b");
-    valor = valor.replace("\\t", "\t");
-    valor = valor.replace("\\n", "\n");
-    valor = valor.replace("\\r", "\r");
-    valor = valor.replace("\\\"", "\"");
-    valor = valor.replace("\\\'", "\'");
-    valor = valor.replace("\\\\", "\\");
-    return {type: 'string', value: valor};
+    let value = text.replace("\\b", "\b");
+    value = value.replace("\\t", "\t");
+    value = value.replace("\\n", "\n");
+    value = value.replace("\\r", "\r");
+    value = value.replace("\\\"", "\"");
+    value = value.replace("\\\'", "\'");
+    value = value.replace("\\\\", "\\");
+    return new Expressions.StringLiteral(value);
   }
 
   getBoolLiteral (token) {
     const val = token.type === this.lexerClass.RK_True ? true : false;
-    return {type: 'bool', value: val};
+    return new Expressions.BoolLiteral(val);
   }
 
   parseArrayLiteral () {
-
+    this.checkOpenCurly();
+    const beginArray = this.getToken();
+    if (this.parsingArrayDimension >= 2) {
+      // TODO: better error message
+      throw new Error(`Array dimensions exceed maximum size of 2 at line ${beginArray.line}`);
+    }
+    this.pos++;
+    this.parsingArrayDimension++;
+    this.consumeNewLines();
+    const data = this.parseExpressionList();
+    this.consumeNewLines();
+    this.checkCloseCurly()
+    this.pos++;
+    this.parsingArrayDimension--;
+    if (this.parsingArrayDimension === 0) {
+      if (!data.isValid) {
+      // TODO: better error message
+      console.log('invalid array');
+      throw new Error(`Invalid array at line ${beginArray.line}`);
+    }
+    }
+    return new Expressions.ArrayLiteral(data);
   }
 
   /*
@@ -327,19 +343,7 @@ export class IVProgParser {
   * @returns object with fields type and value
   **/
   parseVariable (token) {
-    return {type: 'variable', value: token.text};
-  }
-
-  parseFunctions () {
-    let list = [];
-    while(true) {
-      const func = this.parseFunction();
-      if(func === null)
-        break;
-      else
-        list.push(func);
-    }
-    return list;
+    return new Expressions.VariableLiteral(token.text);
   }
 
   /*
@@ -369,7 +373,7 @@ export class IVProgParser {
       this.pos++;
     }
     this.consumeNewLines();
-    const commandsBlock = this.parseFunctionBody();
+    const commandsBlock = this.parseCommandBlock();
     return {returnType: returnType, id: functionID, formalParams: formalParams, block: commandsBlock};
   }
 
@@ -440,9 +444,9 @@ export class IVProgParser {
     throw SyntaxError.createError(this.getTypesAsString(isFunction), token);
   }
 
-  parseFunctionBody () {
+  parseCommandBlock (scope = IVProgParser.FUNCTION) {
     let variablesDecl = [];
-    let commands = [];
+    const commands = [];
     this.checkOpenCurly();
     this.pos++;
     this.consumeNewLines();
@@ -450,6 +454,10 @@ export class IVProgParser {
       const token = this.getToken();
       let cmd = null;
       if (this.isVariableType(token)) {
+        if(scope !== IVProgParser.FUNCTION) {
+          // TODO better error message
+          throw new Error(`Cannot declare variable here (line ${token.line})`);
+        }
         this.pos++;
         variablesDecl = variablesDecl.concat(this.parseDeclararion(token));
         this.checkEOS();
@@ -460,10 +468,14 @@ export class IVProgParser {
       } else if (token.type === this.lexerClass.RK_RETURN) {
         cmd = this.parseReturn();
       } else if (token.type === this.lexerClass.RK_WHILE) {
-
+        cmd = this.parseWhile();
       } else if (token.type === this.lexerClass.RK_FOR) {
-
-      } else if (token.type === this.lexerClass.RK_BREAK) {
+        cmd = this.parseFor();
+      } else if (token.type === this.lexerClass.RK_BREAK ) {
+        if(scope !== IVProgParser.LOOP) {
+          // TODO better error message
+          throw new Error("Break cannot be used outside of a loop.");
+        }
         cmd = this.parseBreak();
       } else if (token.type === this.lexerClass.RK_SWITCH) {
         
@@ -485,19 +497,54 @@ export class IVProgParser {
     return {variables: variablesDecl, commands: commands};
   }
 
+  parseFor () {
+    this.pos++;
+    this.checkOpenParenthesis();
+    this.pos++;
+    this.consumeNewLines();
+    const attribution = this.parseForAttribution();
+    this.consumeNewLines();
+    const condition = this.parseExpressionOR();
+    this.checkEOS();
+    this.pos++;
+    const increment = this.parseForAttribution(true);
+    this.checkCloseParenthesis()
+    this.pos++;
+    this.consumeNewLines();
+    const commandsBlock = this.parseCommandBlock(IVProgParser.LOOP);
+    return new Commands.For(attribution, condition, increment, commandsBlock);
+  }
+
+  parseWhile () {
+    this.pos++;
+    this.checkOpenParenthesis();
+    this.pos++;
+    this.consumeNewLines();
+    const logicalExpression = this.parseExpressionOR();
+    this.consumeNewLines();
+    this.checkCloseParenthesis();
+    this.pos++;
+    this.consumeNewLines();
+    const cmdBlocks = this.parseCommandBlock(IVProgParser.LOOP);
+    return new Commands.While(logicalExpression, cmdBlocks);
+  }
+
   parseBreak () {
     this.pos++;
     this.checkEOS();
     this.pos++;
-    return (new Break());
+    return (new Commands.Break());
   }
 
   parseReturn () {
     this.pos++;
-    const exp = this.parseExpressionOR();
-    this.checkEOS();
+    let exp = null;
+    if(!this.checkEOS(true)) {
+      const exp = this.parseExpressionOR();
+      this.checkEOS();
+    }
     this.pos++;
-    return (new Return(exp));
+    return new Commands.Return(exp);
   }
 
   parseIDCommand () {
@@ -508,17 +555,35 @@ export class IVProgParser {
       const exp = this.parseExpressionOR();
       this.checkEOS();
       this.pos++;
-      return (new Atribution(id, exp));
+      return (new Commands.Atribution(id, exp));
     } else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
       const actualParameters = this.parseActualParameters();
       this.checkEOS();
       this.pos++;
-      return (new FunctionCall(id, actualParameters));
+      return (new Expressions.FunctionCall(id, actualParameters));
     } else {
       throw SyntaxError.createError("= or (", equalOrParenthesis);
     }
   }
 
+  parseForAttribution (isLast = false) {
+    if(!isLast)
+      this.consumeNewLines();
+    if(this.checkEOS(true)) {
+      return null;
+    }
+    const id = this.parseID();
+    const equal = this.getToken();
+    if (equal.type !== this.lexerClass.EQUAL) {
+      throw SyntaxError.createError('=', equal);
+    }
+    this.pos++
+    const exp = this.parseExpressionOR();
+    this.checkEOS();
+    this.pos++;
+    return new Commands.Atribution(id, exp);
+  }
+
   /*
   * Parses an Expression following the structure:
   *
@@ -636,10 +701,14 @@ export class IVProgParser {
       case this.lexerClass.RK_FALSE:
         this.pos++;
         return this.getBoolLiteral(token);
+      case this.lexerClass.OPEN_CURLY:
+        return this.parseArrayLiteral();
       case this.lexerClass.ID:
         return this.parseIDTerm();
       case this.lexerClass.OPEN_PARENTHESIS:
         return this.parseParenthesisExp();
+      default:
+        throw SyntaxError.createError('Terminal', token);
     }
   }
 
@@ -663,7 +732,7 @@ export class IVProgParser {
         this.pos--;
       }
 
-      return new ArrayAccess(id, firstIndex, secondIndex);
+      return new Expressions.ArrayAccess(id, firstIndex, secondIndex);
 
     } else if (this.checkOpenParenthesis(true)) {
       this.pos++;
@@ -677,7 +746,7 @@ export class IVProgParser {
       } else {
         this.pos++;
       }
-      return new FunctionCall(id, actualParameters);
+      return new Expressions.FunctionCall(id, actualParameters);
     } else {
       this.pos = last;
       return id;
@@ -698,22 +767,27 @@ export class IVProgParser {
   parseActualParameters () {
     this.checkOpenParenthesis();
     this.pos++;
-    list = [];
-    while (true) {
-      this.consumeNewLines();
+    this.consumeNewLines();
+    list = this.parseExpressionList();
+    this.consumeNewLines();
+    this.checkCloseParenthesis();
+    this.pos++;
+    return list;
+  }
+
+  parseExpressionList () {
+    const list = [];
+    while(true) {
       const exp = this.parseExpressionOR();
       list.push(exp);
-      const commaToken = this.getToken();
-      if (commaToken.type !== this.lexerClass.COMMA) {
+      const maybeToken = this.getToken();
+      if (maybeToken.type !== this.lexerClass.COMMA) {
         break;
       } else {
         this.pos++;
         this.consumeNewLines();
-      }  
+      }
     }
-    this.consumeNewLines();
-    this.checkCloseParenthesis();
-    this.pos++;
     return list;
   }
 

+ 27 - 17
js/main.js

@@ -10,23 +10,33 @@ const lang = 'pt_br';
 const ivprogLexer = Lexers[lang];
 
 const input = `programa {
-  const real PI
-  const inteiro a[5][5]
-}`;
-let input2 = 'test = i\nb = i + 1\n';
-const lexer = new ivprogLexer(new InputStream(input));
-const stream = new CommonTokenStream(lexer);
-stream.fill();
-let i = 1;
-let token = null;
-while ((token = stream.LT(i)).type !== ivprogLexer.EOF && token.type !== ivprogLexer.WHITESPACE) {
-    console.log(`${token.type}-${token.text}`);
-    console.log('\n')
-    i++;
-}
-const anaSin = new IVProgParser(input2, ivprogLexer);
+        const inteiro a[1][1] = {
+            {
+              1,2,3
+            },
+            {
+              1,3
+            }
+        }
+
+        funcao inicio() {
+            retorna
+        }
+    }`;
+// let input2 = 'test = i\nb = i + 1\n';
+// const lexer = new ivprogLexer(new InputStream(input));
+// const stream = new CommonTokenStream(lexer);
+// stream.fill();
+// let i = 1;
+// let token = null;
+// while ((token = stream.LT(i)).type !== ivprogLexer.EOF && token.type !== ivprogLexer.WHITESPACE) {
+//     console.log(`${token.type}-${token.text}`);
+//     console.log('\n')
+//     i++;
+// }
+const anaSin = new IVProgParser(input, ivprogLexer);
 try {
-  console.log(anaSin.parseIDCommand());
+  console.log(anaSin.parseTree());
 } catch(a) {
   console.log(a);
-}
+}

+ 32 - 0
package-lock.json

@@ -1722,6 +1722,12 @@
       "integrity": "sha512-29nr1EPiHwrJTAHHsEmTt2h+55L8j2GNFdAcYPlRy2NX6iFz7ZZiepVI7kP/QqlnHLq3KvfWpbmGa0d063U09w==",
       "dev": true
     },
+    "capability": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz",
+      "integrity": "sha1-Ua2HNT8ZNv/Xfy8hx0YzpN6oiAE=",
+      "dev": true
+    },
     "caseless": {
       "version": "0.12.0",
       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -2513,6 +2519,17 @@
         "is-arrayish": "^0.2.1"
       }
     },
+    "error-polyfill": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.1.tgz",
+      "integrity": "sha1-J2ZUqtkv8mFVgqMjBmFzzBjaHq8=",
+      "dev": true,
+      "requires": {
+        "capability": "^0.2.5",
+        "o3": "^1.0.3",
+        "u3": "^0.1.0"
+      }
+    },
     "es5-ext": {
       "version": "0.10.46",
       "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz",
@@ -5220,6 +5237,15 @@
       "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
       "dev": true
     },
+    "o3": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/o3/-/o3-1.0.3.tgz",
+      "integrity": "sha1-GSzod6iC36Z1HwQSqGX6+y2h2sA=",
+      "dev": true,
+      "requires": {
+        "capability": "^0.2.5"
+      }
+    },
     "oauth-sign": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@@ -6835,6 +6861,12 @@
       "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
       "dev": true
     },
+    "u3": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.0.tgz",
+      "integrity": "sha1-AGCSdmO2g1PFOc2pnpUR1mh+3Z0=",
+      "dev": true
+    },
     "uglify-es": {
       "version": "3.3.9",
       "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",

+ 1 - 0
package.json

@@ -29,6 +29,7 @@
     "babel-core": "^6.26.3",
     "babel-loader": "^7.1.5",
     "babel-preset-env": "^1.7.0",
+    "error-polyfill": "^0.1.1",
     "jasmine-core": "^3.2.1",
     "karma": "^3.0.0",
     "karma-chrome-launcher": "^2.2.0",

+ 0 - 46
tests/syntax.spec.js

@@ -1,46 +0,0 @@
-import Lexers from './../grammar/';
-import {
-    IVProgParser
-} from './../js/ast/ivprogParser';
-describe("Testing Syntax Analysis for default", () => {
-
-    var input;
-
-    var asa;
-    var lexer;
-
-    it("it should produce a valid tree", () => {
-      lexer  = Lexers['pt_br'];
-      input = `programa {
-      const real PI
-      const inteiro a[5][5]
-      }`;
-
-      asa = {
-          global: [{
-              isConst: true,
-              tipo: 'real',
-              id: 'PI',
-              lines: null,
-              columns: null,
-              initial: null
-          }, {
-              isConst: true,
-              tipo: 'int',
-              id: 'a',
-              lines: {
-                  type: 'int',
-                  value: 5
-              },
-              columns: {
-                  type: 'int',
-                  value: 5
-              },
-              initial: null
-          }],
-          functions: []
-        };
-        const as = new IVProgParser(input, lexer);
-        expect(as.parseTree()).toEqual(asa);
-    });
-});

+ 30 - 0
tests/test00.spec.js

@@ -0,0 +1,30 @@
+import Lexers from './../grammar/';
+import {
+    IVProgParser
+} from './../js/ast/ivprogParser';
+import * as Expressions from './../js/ast/expressions/';
+import * as Commands from './../js/ast/commands/';
+
+describe("Testing Syntax Analysis for default", () => {
+  var lang = 'pt_br';
+  var input;
+
+  var asa;
+  var lexer;
+
+  it("it should produce a valid AST", () => {
+    lexer  = Lexers[lang];
+    input = `programa {
+    const real PI
+    const inteiro a[5][5]
+    }`;
+
+    asa = {
+        global: [new Commands.Declaration('PI', 'real', null, true),
+        new Commands.ArrayDeclaration('a', 'int', new Expressions.IntLiteral(5), new Expressions.IntLiteral(5), null, true)],
+        functions: []
+      };
+      const as = new IVProgParser(input, lexer);
+      expect(as.parseTree()).toEqual(asa);
+  });
+});

tests/newlines.spec.js → tests/test01.spec.js


tests/correctNewline.spec.js → tests/test02.spec.js


tests/expressionEOS.spec.js → tests/test03.spec.js


+ 29 - 0
tests/test04.spec.js

@@ -0,0 +1,29 @@
+import Lexers from './../grammar/';
+import {
+    IVProgParser
+} from './../js/ast/ivprogParser';
+import {
+    SyntaxError
+} from './../js/ast/SyntaxError';
+
+describe('Literal arrays that have more than 2 dimensions', () => {
+    let input = `programa {
+        const inteiro a[1][1] = {
+            {
+                {1,2},
+                {3,4}
+            }
+        }
+
+        funcao inicio() {
+            retorna
+        }
+    }`;
+    const lexer = Lexers['pt_br'];
+
+    it(`should result in SyntaxError`, () => {
+        const as = new IVProgParser(input, lexer);
+        const fun = as.parseTree.bind(as);
+        expect(fun).toThrow();
+    });
+});