|
@@ -1,6 +1,7 @@
|
|
import { CommonTokenStream, InputStream } from 'antlr4/index';
|
|
import { CommonTokenStream, InputStream } from 'antlr4/index';
|
|
import * as Expressions from './expressions/';
|
|
import * as Expressions from './expressions/';
|
|
import * as Commands from './commands/';
|
|
import * as Commands from './commands/';
|
|
|
|
+import { SourceInfo } from './sourceInfo';
|
|
import { Types, toInt, toString } from './types';
|
|
import { Types, toInt, toString } from './types';
|
|
import { convertFromString } from './operators';
|
|
import { convertFromString } from './operators';
|
|
import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
|
|
import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
|
|
@@ -204,7 +205,6 @@ export class IVProgParser {
|
|
|
|
|
|
parseGlobalVariables () {
|
|
parseGlobalVariables () {
|
|
const decl = this.parseMaybeConst();
|
|
const decl = this.parseMaybeConst();
|
|
- const eosToken = this.getToken();
|
|
|
|
this.checkEOS();
|
|
this.checkEOS();
|
|
this.pos++;
|
|
this.pos++;
|
|
return decl;
|
|
return decl;
|
|
@@ -239,7 +239,9 @@ export class IVProgParser {
|
|
let initial = null;
|
|
let initial = null;
|
|
let dim1 = null;
|
|
let dim1 = null;
|
|
let dim2 = null;
|
|
let dim2 = null;
|
|
|
|
+ const idToken = this.getToken();
|
|
const idString = this.parseID();
|
|
const idString = this.parseID();
|
|
|
|
+
|
|
// Check for array or vector
|
|
// Check for array or vector
|
|
// ID[int/IDi][int/IDj]
|
|
// ID[int/IDi][int/IDj]
|
|
if (this.checkOpenBrace(true)) {
|
|
if (this.checkOpenBrace(true)) {
|
|
@@ -260,6 +262,9 @@ export class IVProgParser {
|
|
}
|
|
}
|
|
|
|
|
|
const equalsToken = this.getToken();
|
|
const equalsToken = this.getToken();
|
|
|
|
+ if(isConst && equalsToken.type !== this.lexerClass.EQUAL ) {
|
|
|
|
+ throw SyntaxErrorFactory.const_not_init(idToken);
|
|
|
|
+ }
|
|
if(equalsToken.type === this.lexerClass.EQUAL) {
|
|
if(equalsToken.type === this.lexerClass.EQUAL) {
|
|
this.pos++;
|
|
this.pos++;
|
|
initial = this.parseExpressionOR();
|
|
initial = this.parseExpressionOR();
|
|
@@ -271,6 +276,7 @@ export class IVProgParser {
|
|
} else {
|
|
} else {
|
|
declaration = new Commands.Declaration(idString, typeString, initial, isConst);
|
|
declaration = new Commands.Declaration(idString, typeString, initial, isConst);
|
|
}
|
|
}
|
|
|
|
+ declaration.sourceInfo = SourceInfo.createSourceInfo(idToken);
|
|
const commaToken = this.getToken();
|
|
const commaToken = this.getToken();
|
|
if(commaToken.type === this.lexerClass.COMMA) {
|
|
if(commaToken.type === this.lexerClass.COMMA) {
|
|
this.pos++;
|
|
this.pos++;
|
|
@@ -320,21 +326,33 @@ export class IVProgParser {
|
|
**/
|
|
**/
|
|
getIntLiteral (token) {
|
|
getIntLiteral (token) {
|
|
const text = token.text;
|
|
const text = token.text;
|
|
- return new Expressions.IntLiteral(toInt(text));
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.IntLiteral(toInt(text));
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
getRealLiteral (token) {
|
|
getRealLiteral (token) {
|
|
- return new Expressions.RealLiteral(parseFloat(token.text));
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.RealLiteral(parseFloat(token.text));
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
getStringLiteral (token) {
|
|
getStringLiteral (token) {
|
|
const text = token.text;
|
|
const text = token.text;
|
|
- return new Expressions.StringLiteral(toString(text));
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.StringLiteral(toString(text));
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
getBoolLiteral (token) {
|
|
getBoolLiteral (token) {
|
|
const val = token.type === this.lexerClass.RK_TRUE ? true : false;
|
|
const val = token.type === this.lexerClass.RK_TRUE ? true : false;
|
|
- return new Expressions.BoolLiteral(val);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.BoolLiteral(val);
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
parseArrayLiteral () {
|
|
parseArrayLiteral () {
|
|
@@ -350,6 +368,7 @@ export class IVProgParser {
|
|
const data = this.parseExpressionList();
|
|
const data = this.parseExpressionList();
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
this.checkCloseCurly()
|
|
this.checkCloseCurly()
|
|
|
|
+ const endArray = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
this.parsingArrayDimension--;
|
|
this.parsingArrayDimension--;
|
|
if (this.parsingArrayDimension === 0) {
|
|
if (this.parsingArrayDimension === 0) {
|
|
@@ -359,7 +378,10 @@ export class IVProgParser {
|
|
// throw new Error(`Invalid array at line ${beginArray.line}`);
|
|
// throw new Error(`Invalid array at line ${beginArray.line}`);
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
- return new Expressions.ArrayLiteral(data);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfoFromList(beginArray, endArray);
|
|
|
|
+ const exp = new Expressions.ArrayLiteral(data);
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -367,7 +389,10 @@ export class IVProgParser {
|
|
* @returns object with fields type and value
|
|
* @returns object with fields type and value
|
|
**/
|
|
**/
|
|
parseVariable (token) {
|
|
parseVariable (token) {
|
|
- return new Expressions.VariableLiteral(token.text);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.VariableLiteral(token.text);
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -700,11 +725,14 @@ export class IVProgParser {
|
|
const id = this.parseID();
|
|
const id = this.parseID();
|
|
const equalOrParenthesis = this.getToken();
|
|
const equalOrParenthesis = this.getToken();
|
|
if (equalOrParenthesis.type === this.lexerClass.EQUAL) {
|
|
if (equalOrParenthesis.type === this.lexerClass.EQUAL) {
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(this.getToken());
|
|
this.pos++
|
|
this.pos++
|
|
const exp = this.parseExpressionOR();
|
|
const exp = this.parseExpressionOR();
|
|
this.checkEOS();
|
|
this.checkEOS();
|
|
this.pos++;
|
|
this.pos++;
|
|
- return (new Commands.Assign(id, exp));
|
|
|
|
|
|
+ const cmd = new Commands.Assign(id, exp);
|
|
|
|
+ cmd.sourceInfo = sourceInfo;
|
|
|
|
+ return cmd;
|
|
} else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
|
|
} else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
|
|
const funcCall = this.parseFunctionCallCommand(id);
|
|
const funcCall = this.parseFunctionCallCommand(id);
|
|
this.checkEOS();
|
|
this.checkEOS();
|
|
@@ -731,7 +759,10 @@ export class IVProgParser {
|
|
if(!isLast) {
|
|
if(!isLast) {
|
|
this.consumeForSemiColon();
|
|
this.consumeForSemiColon();
|
|
}
|
|
}
|
|
- return new Commands.Assign(id, exp);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(equal);
|
|
|
|
+ const cmd = new Commands.Assign(id, exp);
|
|
|
|
+ cmd.sourceInfo = sourceInfo;
|
|
|
|
+ return cmd;
|
|
}
|
|
}
|
|
|
|
|
|
parseCases () {
|
|
parseCases () {
|
|
@@ -793,11 +824,13 @@ export class IVProgParser {
|
|
parseExpressionOR () {
|
|
parseExpressionOR () {
|
|
let exp1 = this.parseExpressionAND();
|
|
let exp1 = this.parseExpressionAND();
|
|
while (this.getToken().type === this.lexerClass.OR_OPERATOR) {
|
|
while (this.getToken().type === this.lexerClass.OR_OPERATOR) {
|
|
|
|
+ const opToken = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
const or = convertFromString('or');
|
|
const or = convertFromString('or');
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
const exp2 = this.parseExpressionAND();
|
|
const exp2 = this.parseExpressionAND();
|
|
const finalExp = new Expressions.InfixApp(or, exp1, exp2);
|
|
const finalExp = new Expressions.InfixApp(or, exp1, exp2);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(opToken);
|
|
exp1 = finalExp
|
|
exp1 = finalExp
|
|
}
|
|
}
|
|
return exp1;
|
|
return exp1;
|
|
@@ -806,11 +839,13 @@ export class IVProgParser {
|
|
parseExpressionAND () {
|
|
parseExpressionAND () {
|
|
let exp1 = this.parseExpressionNot();
|
|
let exp1 = this.parseExpressionNot();
|
|
while (this.getToken().type === this.lexerClass.AND_OPERATOR) {
|
|
while (this.getToken().type === this.lexerClass.AND_OPERATOR) {
|
|
|
|
+ const opToken = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
const and = convertFromString('and');
|
|
const and = convertFromString('and');
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
const exp2 = this.parseExpressionNot();
|
|
const exp2 = this.parseExpressionNot();
|
|
const finalExp = new Expressions.InfixApp(and, exp1, exp2);
|
|
const finalExp = new Expressions.InfixApp(and, exp1, exp2);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(opToken);
|
|
exp1 = finalExp;
|
|
exp1 = finalExp;
|
|
}
|
|
}
|
|
return exp1;
|
|
return exp1;
|
|
@@ -819,10 +854,14 @@ export class IVProgParser {
|
|
parseExpressionNot () {
|
|
parseExpressionNot () {
|
|
const maybeNotToken = this.getToken();
|
|
const maybeNotToken = this.getToken();
|
|
if (maybeNotToken.type === this.lexerClass.NOT_OPERATOR) {
|
|
if (maybeNotToken.type === this.lexerClass.NOT_OPERATOR) {
|
|
|
|
+ const opToken = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
const not = convertFromString('not');
|
|
const not = convertFromString('not');
|
|
const exp1 = this.parseExpressionRel();
|
|
const exp1 = this.parseExpressionRel();
|
|
- return new Expressions.UnaryApp(not, exp1);
|
|
|
|
|
|
+ finalExp = new Expressions.UnaryApp(not, exp1);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(opToken);
|
|
|
|
+ return finalExp;
|
|
|
|
+
|
|
} else {
|
|
} else {
|
|
return this.parseExpressionRel();
|
|
return this.parseExpressionRel();
|
|
}
|
|
}
|
|
@@ -836,6 +875,7 @@ export class IVProgParser {
|
|
const rel = convertFromString(relToken.text);
|
|
const rel = convertFromString(relToken.text);
|
|
const exp2 = this.parseExpression();
|
|
const exp2 = this.parseExpression();
|
|
const finalExp = new Expressions.InfixApp(rel, exp1, exp2);
|
|
const finalExp = new Expressions.InfixApp(rel, exp1, exp2);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(relToken);
|
|
exp1 = finalExp;
|
|
exp1 = finalExp;
|
|
}
|
|
}
|
|
return exp1;
|
|
return exp1;
|
|
@@ -849,6 +889,7 @@ export class IVProgParser {
|
|
const op = convertFromString(sumOpToken.text);
|
|
const op = convertFromString(sumOpToken.text);
|
|
const factor2 = this.parseFactor();
|
|
const factor2 = this.parseFactor();
|
|
const finalExp = new Expressions.InfixApp(op, factor, factor2);
|
|
const finalExp = new Expressions.InfixApp(op, factor, factor2);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(sumOpToken);
|
|
factor = finalExp;
|
|
factor = finalExp;
|
|
}
|
|
}
|
|
return factor;
|
|
return factor;
|
|
@@ -862,6 +903,7 @@ export class IVProgParser {
|
|
const op = convertFromString(multOpToken.text);
|
|
const op = convertFromString(multOpToken.text);
|
|
const term2 =this.parseTerm();
|
|
const term2 =this.parseTerm();
|
|
const finalExp = new Expressions.InfixApp(op, term, term2);
|
|
const finalExp = new Expressions.InfixApp(op, term, term2);
|
|
|
|
+ finalExp.sourceInfo = SourceInfo.createSourceInfo(multOpToken);
|
|
term = finalExp;
|
|
term = finalExp;
|
|
}
|
|
}
|
|
return term;
|
|
return term;
|
|
@@ -869,10 +911,14 @@ export class IVProgParser {
|
|
|
|
|
|
parseTerm () {
|
|
parseTerm () {
|
|
const token = this.getToken();
|
|
const token = this.getToken();
|
|
|
|
+ let sourceInfo = null;
|
|
switch(token.type) {
|
|
switch(token.type) {
|
|
case this.lexerClass.SUM_OP:
|
|
case this.lexerClass.SUM_OP:
|
|
this.pos++;
|
|
this.pos++;
|
|
- return new Expressions.UnaryApp(convertFromString(token.text), this.parseTerm());
|
|
|
|
|
|
+ sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
|
+ const exp = new Expressions.UnaryApp(convertFromString(token.text), this.parseTerm());
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
case this.lexerClass.INTEGER:
|
|
case this.lexerClass.INTEGER:
|
|
this.pos++;
|
|
this.pos++;
|
|
return this.getIntLiteral(token);
|
|
return this.getIntLiteral(token);
|
|
@@ -899,29 +945,36 @@ export class IVProgParser {
|
|
|
|
|
|
parseIDTerm () {
|
|
parseIDTerm () {
|
|
const id = this.parseID();
|
|
const id = this.parseID();
|
|
- const last = this.pos;
|
|
|
|
|
|
+ const tokenA = this.getToken(this.pos - 1);
|
|
if(this.checkOpenBrace(true)) {
|
|
if(this.checkOpenBrace(true)) {
|
|
|
|
+ let tokenB = null;
|
|
this.pos++;
|
|
this.pos++;
|
|
const firstIndex = this.parseExpression();
|
|
const firstIndex = this.parseExpression();
|
|
let secondIndex = null;
|
|
let secondIndex = null;
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
this.checkCloseBrace();
|
|
this.checkCloseBrace();
|
|
|
|
+ tokenB = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
if(this.checkOpenBrace(true)){
|
|
if(this.checkOpenBrace(true)){
|
|
this.pos++;
|
|
this.pos++;
|
|
secondIndex = this.parseExpression();
|
|
secondIndex = this.parseExpression();
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
this.checkCloseBrace();
|
|
this.checkCloseBrace();
|
|
|
|
+ tokenB = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return new Expressions.ArrayAccess(id, firstIndex, secondIndex);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfoFromList(tokenA, tokenB);
|
|
|
|
+ const exp = new Expressions.ArrayAccess(id, firstIndex, secondIndex);
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
|
|
|
|
} else if (this.checkOpenParenthesis(true)) {
|
|
} else if (this.checkOpenParenthesis(true)) {
|
|
return this.parseFunctionCallExpression(id);
|
|
return this.parseFunctionCallExpression(id);
|
|
} else {
|
|
} else {
|
|
- this.pos = last;
|
|
|
|
- return new Expressions.VariableLiteral(id);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfo(tokenA);
|
|
|
|
+ const exp = new Expressions.VariableLiteral(id);
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
|
|
+ return exp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -936,9 +989,14 @@ export class IVProgParser {
|
|
}
|
|
}
|
|
|
|
|
|
parseFunctionCallExpression (id) {
|
|
parseFunctionCallExpression (id) {
|
|
|
|
+ const tokenA = this.getToken(this.pos - 1);
|
|
const actualParameters = this.parseActualParameters();
|
|
const actualParameters = this.parseActualParameters();
|
|
|
|
+ const tokenB = this.getToken(this.pos - 1);
|
|
const funcName = this.getFunctionName(id);
|
|
const funcName = this.getFunctionName(id);
|
|
- return new Expressions.FunctionCall(funcName, actualParameters);
|
|
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfoFromList(tokenA, tokenB);
|
|
|
|
+ const cmd = new Expressions.FunctionCall(funcName, actualParameters);
|
|
|
|
+ cmd.sourceInfo = sourceInfo;
|
|
|
|
+ return cmd;
|
|
}
|
|
}
|
|
|
|
|
|
parseFunctionCallCommand (id) {
|
|
parseFunctionCallCommand (id) {
|
|
@@ -947,12 +1005,16 @@ export class IVProgParser {
|
|
|
|
|
|
parseParenthesisExp () {
|
|
parseParenthesisExp () {
|
|
this.checkOpenParenthesis();
|
|
this.checkOpenParenthesis();
|
|
|
|
+ const tokenA = this.getToken();
|
|
this.pos++;
|
|
this.pos++;
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
const exp = this.parseExpressionOR();
|
|
const exp = this.parseExpressionOR();
|
|
this.consumeNewLines();
|
|
this.consumeNewLines();
|
|
this.checkCloseParenthesis();
|
|
this.checkCloseParenthesis();
|
|
|
|
+ const tokenB = this.getToken();
|
|
|
|
+ const sourceInfo = SourceInfo.createSourceInfoFromList(tokenA, tokenB);
|
|
this.pos++;
|
|
this.pos++;
|
|
|
|
+ exp.sourceInfo = sourceInfo;
|
|
return exp;
|
|
return exp;
|
|
}
|
|
}
|
|
|
|
|