|
@@ -1,7 +1,5 @@
|
|
|
-import { CommonTokenStream, InputStream } from "antlr4/index";
|
|
|
import * as Expressions from "./expressions";
|
|
|
import * as Commands from "./commands";
|
|
|
-import * as AstHelpers from "./ast_helpers";
|
|
|
import * as Parsers from "../typeSystem/parsers";
|
|
|
import { Types } from "../typeSystem/types";
|
|
|
import { ArrayType } from "../typeSystem/array_type";
|
|
@@ -12,9 +10,13 @@ import { LanguageDefinedFunction } from "../processor/definedFunctions";
|
|
|
import { LanguageService } from "../services/languageService";
|
|
|
|
|
|
export class IVProgParser {
|
|
|
- static createParser (input) {
|
|
|
- const lexerClass = LanguageService.getCurrentLexer();
|
|
|
- return new IVProgParser(input, lexerClass);
|
|
|
+ static createParser (input, fill = true) {
|
|
|
+ const lexer = LanguageService.getCurrentLexer();
|
|
|
+ const parser = new IVProgParser(input, lexer);
|
|
|
+ if (fill) {
|
|
|
+ parser.fill()
|
|
|
+ }
|
|
|
+ return parser
|
|
|
}
|
|
|
|
|
|
// <BEGIN scope consts>
|
|
@@ -32,37 +34,63 @@ export class IVProgParser {
|
|
|
}
|
|
|
// </ END scope consts>
|
|
|
|
|
|
- constructor (input, lexerClass) {
|
|
|
- this.lexerClass = lexerClass;
|
|
|
- this.inputStream = new InputStream(input);
|
|
|
- this.lexer = new lexerClass(this.inputStream);
|
|
|
- this.lexer.recover = AstHelpers.recover.bind(this.lexer);
|
|
|
- this.tokenStream = new CommonTokenStream(this.lexer);
|
|
|
- this.tokenStream.fill();
|
|
|
- this.pos = 1;
|
|
|
- this.variableTypes = [
|
|
|
- this.lexerClass.RK_INTEGER,
|
|
|
- this.lexerClass.RK_REAL,
|
|
|
- this.lexerClass.RK_BOOLEAN,
|
|
|
- this.lexerClass.RK_STRING,
|
|
|
- this.lexerClass.RK_CHARACTER,
|
|
|
- ];
|
|
|
- this.functionTypes = this.variableTypes.concat(this.lexerClass.RK_VOID);
|
|
|
+ /**
|
|
|
+ * @param {string} input
|
|
|
+ * @param {IVProgLexer} ivprogLexer
|
|
|
+ **/
|
|
|
+ constructor (input, ivprogLexer) {
|
|
|
+ this.ivprogLexer = ivprogLexer;
|
|
|
+ this.inputStream = input;
|
|
|
+ this.lexer = ivprogLexer.lexer;
|
|
|
+ this.tokenStream = [];
|
|
|
+ this.pos = 0;
|
|
|
+ this.ruleNames = ivprogLexer.getRules();
|
|
|
+ this.variableTypes = Object.entries(this.ivprogLexer.getTypeKeys()).map(
|
|
|
+ ([key, _]) => key
|
|
|
+ );
|
|
|
+ this.functionTypes = this.variableTypes.concat(this.ruleNames.RK_VOID);
|
|
|
+
|
|
|
this.parsingArrayDimension = 0;
|
|
|
this.scope = [];
|
|
|
- this.langFuncs = LanguageService.getCurrentLangFuncs();
|
|
|
+ this.langFuncs = this.ivprogLexer.getLangFuncs();
|
|
|
this.definedFuncsNameList = [];
|
|
|
this.definedVariablesStack = [];
|
|
|
}
|
|
|
|
|
|
+ fill (stream = null) {
|
|
|
+ if (stream) {
|
|
|
+ this.tokenStream = stream;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.tokenStream = Array.from(this.lexer.reset(this.inputStream));
|
|
|
+ this.tokenStream = this.tokenStream.filter((token) => {
|
|
|
+ // Throws an exception in case of invalid syntax
|
|
|
+ if (token.type === this.ruleNames.ERROR) {
|
|
|
+ let text = token.text;
|
|
|
+ const line = token.line;
|
|
|
+ const column = token.col;
|
|
|
+ throw SyntaxErrorFactory.invalid_syntax(text, line, column);
|
|
|
+ }
|
|
|
+ // remove all whitespaces token and comments
|
|
|
+ return (
|
|
|
+ token.type !== this.ruleNames.WHITESPACE &&
|
|
|
+ token.type !== this.ruleNames.COMMENTS
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
parseTree () {
|
|
|
return this.parseProgram();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @param {number} index
|
|
|
+ * @return {moo.Token}
|
|
|
+ * */
|
|
|
getToken (index = this.pos) {
|
|
|
// if(index === null)
|
|
|
// index = this.pos;
|
|
|
- return this.tokenStream.LT(index);
|
|
|
+ return this.tokenStream[index];
|
|
|
}
|
|
|
|
|
|
insideScope (scope) {
|
|
@@ -94,8 +122,7 @@ export class IVProgParser {
|
|
|
}
|
|
|
|
|
|
isEOF () {
|
|
|
- this.getToken(this.pos);
|
|
|
- return this.tokenStream.fetchedEOF;
|
|
|
+ return this.getToken(this.pos) == null;
|
|
|
}
|
|
|
|
|
|
parseProgram () {
|
|
@@ -104,7 +131,7 @@ export class IVProgParser {
|
|
|
let globalVars = [];
|
|
|
let functions = [];
|
|
|
|
|
|
- if (this.lexerClass.RK_PROGRAM === token.type) {
|
|
|
+ if (this.ruleNames.RK_PROGRAM === token.type) {
|
|
|
this.pos++;
|
|
|
this.consumeNewLines();
|
|
|
this.checkOpenCurly();
|
|
@@ -114,11 +141,11 @@ export class IVProgParser {
|
|
|
this.consumeNewLines();
|
|
|
const token = this.getToken();
|
|
|
if (
|
|
|
- token.type === this.lexerClass.RK_CONST ||
|
|
|
+ token.type === this.ruleNames.RK_CONST ||
|
|
|
this.isVariableType(token)
|
|
|
) {
|
|
|
globalVars = globalVars.concat(this.parseGlobalVariables());
|
|
|
- } else if (token.type === this.lexerClass.RK_FUNCTION) {
|
|
|
+ } else if (token.type === this.ruleNames.RK_FUNCTION) {
|
|
|
this.pushVariableStack();
|
|
|
functions = functions.concat(this.parseFunction());
|
|
|
this.popVariableStack();
|
|
@@ -137,7 +164,7 @@ export class IVProgParser {
|
|
|
return { global: globalVars, functions: functions };
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.token_missing_one(
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_PROGRAM],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_PROGRAM],
|
|
|
token
|
|
|
);
|
|
|
}
|
|
@@ -145,7 +172,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkOpenCurly (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.OPEN_CURLY !== token.type) {
|
|
|
+ if (this.ruleNames.OPEN_CURLY !== token.type) {
|
|
|
if (!attempt) throw SyntaxErrorFactory.token_missing_one("{", token);
|
|
|
else return false;
|
|
|
}
|
|
@@ -154,7 +181,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkCloseCurly (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.CLOSE_CURLY !== token.type) {
|
|
|
+ if (this.ruleNames.CLOSE_CURLY !== token.type) {
|
|
|
if (!attempt) throw SyntaxErrorFactory.token_missing_one("}", token);
|
|
|
else return false;
|
|
|
}
|
|
@@ -171,7 +198,7 @@ export class IVProgParser {
|
|
|
**/
|
|
|
checkOpenBrace (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.OPEN_BRACE !== token.type) {
|
|
|
+ if (this.ruleNames.OPEN_BRACE !== token.type) {
|
|
|
if (!attempt) {
|
|
|
throw SyntaxErrorFactory.token_missing_one("[", token);
|
|
|
} else {
|
|
@@ -183,7 +210,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkCloseBrace (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.CLOSE_BRACE !== token.type) {
|
|
|
+ if (this.ruleNames.CLOSE_BRACE !== token.type) {
|
|
|
if (!attempt) {
|
|
|
throw SyntaxErrorFactory.token_missing_one("]", token);
|
|
|
} else {
|
|
@@ -195,7 +222,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkOpenParenthesis (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.OPEN_PARENTHESIS !== token.type) {
|
|
|
+ if (this.ruleNames.OPEN_PARENTHESIS !== token.type) {
|
|
|
if (!attempt) {
|
|
|
throw SyntaxErrorFactory.token_missing_one("(", token);
|
|
|
} else {
|
|
@@ -207,7 +234,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkCloseParenthesis (attempt = false) {
|
|
|
const token = this.getToken();
|
|
|
- if (this.lexerClass.CLOSE_PARENTHESIS !== token.type) {
|
|
|
+ if (this.ruleNames.CLOSE_PARENTHESIS !== token.type) {
|
|
|
if (!attempt) {
|
|
|
throw SyntaxErrorFactory.token_missing_one(")", token);
|
|
|
} else {
|
|
@@ -219,7 +246,7 @@ export class IVProgParser {
|
|
|
|
|
|
checkEOS (attempt = false) {
|
|
|
const eosToken = this.getToken();
|
|
|
- if (eosToken.type !== this.lexerClass.EOS) {
|
|
|
+ if (eosToken.type !== this.ruleNames.EOS) {
|
|
|
if (!attempt) throw SyntaxErrorFactory.eos_missing(eosToken);
|
|
|
else return false;
|
|
|
}
|
|
@@ -245,7 +272,7 @@ export class IVProgParser {
|
|
|
|
|
|
consumeForSemiColon () {
|
|
|
const eosToken = this.getToken();
|
|
|
- if (eosToken.type === this.lexerClass.EOS && eosToken.text.match(";")) {
|
|
|
+ if (eosToken.type === this.ruleNames.EOS && eosToken.text.match("^;$")) {
|
|
|
this.pos++;
|
|
|
return;
|
|
|
}
|
|
@@ -266,7 +293,7 @@ export class IVProgParser {
|
|
|
**/
|
|
|
parseMaybeConst () {
|
|
|
const constToken = this.getToken();
|
|
|
- if (constToken.type === this.lexerClass.RK_CONST) {
|
|
|
+ if (constToken.type === this.ruleNames.RK_CONST) {
|
|
|
this.pos++;
|
|
|
const typeString = this.parseType();
|
|
|
return this.parseDeclaration(typeString, true);
|
|
@@ -275,7 +302,7 @@ export class IVProgParser {
|
|
|
return this.parseDeclaration(typeString);
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.token_missing_list(
|
|
|
- [this.lexer.literalNames[this.lexerClass.RK_CONST]].concat(
|
|
|
+ [this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_CONST]].concat(
|
|
|
this.getTypeArray()
|
|
|
),
|
|
|
constToken
|
|
@@ -283,9 +310,9 @@ export class IVProgParser {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
+ /**
|
|
|
* Parses a declarion of the form: type --- id --- (= --- EAnd)?
|
|
|
- * @returns a list of Declararion(const, type, id, initVal?)
|
|
|
+ * @return {Commands.Declartion[]} a list of Declararion(const, type, id, initVal?)
|
|
|
**/
|
|
|
parseDeclaration (typeString, isConst = false) {
|
|
|
let initial = null;
|
|
@@ -324,11 +351,11 @@ export class IVProgParser {
|
|
|
dim2
|
|
|
);
|
|
|
} else {
|
|
|
- const equalsToken = this.getToken();
|
|
|
- if (isConst && equalsToken.type !== this.lexerClass.EQUAL) {
|
|
|
+ const assignmentToken = this.getToken();
|
|
|
+ if (isConst && assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
|
|
|
throw SyntaxErrorFactory.const_not_init(sourceInfo);
|
|
|
}
|
|
|
- if (equalsToken.type === this.lexerClass.EQUAL) {
|
|
|
+ if (assignmentToken.type === this.ruleNames.ASSIGNMENT) {
|
|
|
this.pos++;
|
|
|
initial = this.parseExpressionOR();
|
|
|
}
|
|
@@ -340,7 +367,7 @@ export class IVProgParser {
|
|
|
);
|
|
|
declaration.sourceInfo = sourceInfo;
|
|
|
const commaToken = this.getToken();
|
|
|
- if (commaToken.type === this.lexerClass.COMMA) {
|
|
|
+ if (commaToken.type === this.ruleNames.COMMA) {
|
|
|
this.pos++;
|
|
|
this.consumeNewLines();
|
|
|
return [declaration].concat(this.parseDeclaration(typeString, isConst));
|
|
@@ -359,7 +386,7 @@ export class IVProgParser {
|
|
|
dim1,
|
|
|
dim2
|
|
|
) {
|
|
|
- const equalsToken = this.getToken();
|
|
|
+ const assignmentToken = this.getToken();
|
|
|
let n_lines = dim1;
|
|
|
let n_columns = dim2;
|
|
|
let initial = null;
|
|
@@ -371,22 +398,22 @@ export class IVProgParser {
|
|
|
dim_is_id = true;
|
|
|
if (dimensions > 1 && (dim1 == null || dim2 == null)) {
|
|
|
throw SyntaxErrorFactory.invalid_matrix_id_dimension(
|
|
|
- SourceInfo.createSourceInfo(equalsToken)
|
|
|
+ SourceInfo.createSourceInfo(assignmentToken)
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
- if (isConst && equalsToken.type !== this.lexerClass.EQUAL) {
|
|
|
+ if (isConst && assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
|
|
|
throw SyntaxErrorFactory.const_not_init(sourceInfo);
|
|
|
}
|
|
|
- if (equalsToken.type === this.lexerClass.EQUAL) {
|
|
|
+ if (assignmentToken.type === this.ruleNames.ASSIGNMENT) {
|
|
|
if (dim_is_id) {
|
|
|
if (dimensions == 1) {
|
|
|
throw SyntaxErrorFactory.invalid_vector_init(
|
|
|
- SourceInfo.createSourceInfo(equalsToken)
|
|
|
+ SourceInfo.createSourceInfo(assignmentToken)
|
|
|
);
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.invalid_matrix_init(
|
|
|
- SourceInfo.createSourceInfo(equalsToken)
|
|
|
+ SourceInfo.createSourceInfo(assignmentToken)
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -445,7 +472,7 @@ export class IVProgParser {
|
|
|
);
|
|
|
declaration.sourceInfo = sourceInfo;
|
|
|
const commaToken = this.getToken();
|
|
|
- if (commaToken.type === this.lexerClass.COMMA) {
|
|
|
+ if (commaToken.type === this.ruleNames.COMMA) {
|
|
|
this.pos++;
|
|
|
this.consumeNewLines();
|
|
|
return [declaration].concat(this.parseDeclaration(typeString, isConst));
|
|
@@ -456,7 +483,11 @@ export class IVProgParser {
|
|
|
|
|
|
consumeNewLines () {
|
|
|
let token = this.getToken();
|
|
|
- while (token.type === this.lexerClass.EOS && token.text.match("[\r\n]+")) {
|
|
|
+ while (
|
|
|
+ token &&
|
|
|
+ token.type === this.ruleNames.EOS &&
|
|
|
+ token.text.match("^[\r\n]+$")
|
|
|
+ ) {
|
|
|
this.pos++;
|
|
|
token = this.getToken();
|
|
|
}
|
|
@@ -466,34 +497,35 @@ export class IVProgParser {
|
|
|
return this.variableTypes.find((v) => v === token.type);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
+ /**
|
|
|
* Reads the next token of the stream to check if it is a Integer or an ID.
|
|
|
* @returns Integer | ID
|
|
|
**/
|
|
|
parseArrayDimension () {
|
|
|
const dimToken = this.getToken();
|
|
|
- if (dimToken.type === this.lexerClass.INTEGER) {
|
|
|
+ if (dimToken.type === this.ruleNames.INTEGER) {
|
|
|
//parse as int literal
|
|
|
this.pos++;
|
|
|
return this.getIntLiteral(dimToken);
|
|
|
- } else if (dimToken.type === this.lexerClass.ID) {
|
|
|
+ } else if (dimToken.type === this.ruleNames.ID) {
|
|
|
//parse as variable
|
|
|
this.pos++;
|
|
|
return this.parseVariable(dimToken);
|
|
|
- } else if (dimToken.type === this.lexerClass.CLOSE_BRACE) {
|
|
|
+ } else if (dimToken.type === this.ruleNames.CLOSE_BRACE) {
|
|
|
return null;
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.invalid_array_dimension(
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_INTEGER],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_INTEGER],
|
|
|
dimToken
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
+ /**
|
|
|
* Returns an object {type: 'int', value: value}.
|
|
|
* It checks for binary and hexadecimal integers.
|
|
|
- * @returns object with fields type and value
|
|
|
+ * @param {moo.Token} token
|
|
|
+ * @return {Object} object with fields type and value
|
|
|
**/
|
|
|
getIntLiteral (token) {
|
|
|
const text = token.text;
|
|
@@ -608,9 +640,9 @@ export class IVProgParser {
|
|
|
if (lastSize == null) {
|
|
|
lastSize = data.length;
|
|
|
} else if (lastSize !== data.length) {
|
|
|
- const expString = this.inputStream.getText(
|
|
|
- beginArray.start,
|
|
|
- endArray.stop
|
|
|
+ const expString = this.inputStream.substring(
|
|
|
+ beginArray.offset,
|
|
|
+ endArray.offset + endArray.text.length
|
|
|
);
|
|
|
throw SyntaxErrorFactory.invalid_matrix_literal_line(
|
|
|
expString,
|
|
@@ -622,7 +654,7 @@ export class IVProgParser {
|
|
|
exp.sourceInfo = sourceInfo;
|
|
|
list.push(exp);
|
|
|
const commaToken = this.getToken();
|
|
|
- if (commaToken.type !== this.lexerClass.COMMA) {
|
|
|
+ if (commaToken.type !== this.ruleNames.COMMA) {
|
|
|
break;
|
|
|
}
|
|
|
this.pos += 1;
|
|
@@ -654,7 +686,7 @@ export class IVProgParser {
|
|
|
this.pushScope(IVProgParser.FUNCTION);
|
|
|
let formalParams = [];
|
|
|
const token = this.getToken();
|
|
|
- if (token.type !== this.lexerClass.RK_FUNCTION) {
|
|
|
+ if (token.type !== this.ruleNames.RK_FUNCTION) {
|
|
|
//throw SyntaxError.createError(this.lexer.literalNames[this.lexerClass.PR_FUNCAO], token);
|
|
|
return null;
|
|
|
}
|
|
@@ -702,7 +734,7 @@ export class IVProgParser {
|
|
|
if (functionID === null && !func.isMain) {
|
|
|
throw SyntaxErrorFactory.invalid_main_return(
|
|
|
LanguageDefinedFunction.getMainFunctionName(),
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_VOID],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_VOID],
|
|
|
token.line
|
|
|
);
|
|
|
} else if (func.isMain && formalParams.length !== 0) {
|
|
@@ -723,7 +755,7 @@ export class IVProgParser {
|
|
|
let reference = false;
|
|
|
const typeString = this.parseType();
|
|
|
let maybeIDToken = this.getToken();
|
|
|
- if (maybeIDToken.type === this.lexerClass.RK_REFERENCE) {
|
|
|
+ if (maybeIDToken.type === this.ruleNames.RK_REFERENCE) {
|
|
|
reference = true;
|
|
|
this.pos += 1;
|
|
|
maybeIDToken = this.getToken();
|
|
@@ -752,7 +784,7 @@ export class IVProgParser {
|
|
|
parameter.sourceInfo = SourceInfo.createSourceInfo(maybeIDToken);
|
|
|
list.push(parameter);
|
|
|
const commaToken = this.getToken();
|
|
|
- if (commaToken.type !== this.lexerClass.COMMA) break;
|
|
|
+ if (commaToken.type !== this.ruleNames.COMMA) break;
|
|
|
this.pos++;
|
|
|
this.consumeNewLines();
|
|
|
}
|
|
@@ -761,7 +793,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseID () {
|
|
|
const token = this.getToken();
|
|
|
- if (token.type !== this.lexerClass.ID) {
|
|
|
+ if (token.type !== this.ruleNames.ID) {
|
|
|
throw SyntaxErrorFactory.id_missing(token);
|
|
|
}
|
|
|
this.pos++;
|
|
@@ -773,14 +805,24 @@ export class IVProgParser {
|
|
|
return token.text;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @return {string}
|
|
|
+ **/
|
|
|
parseMaybeLibID () {
|
|
|
const token = this.getToken();
|
|
|
- if (
|
|
|
- token.type !== this.lexerClass.ID &&
|
|
|
- token.type !== this.lexerClass.LIB_ID
|
|
|
- ) {
|
|
|
+ if (token.type !== this.ruleNames.ID) {
|
|
|
throw SyntaxErrorFactory.id_missing(token);
|
|
|
}
|
|
|
+ const maybeDOT = this.getToken(this.pos + 1);
|
|
|
+ if (maybeDOT.type === this.ruleNames.DOT) {
|
|
|
+ this.pos += 2;
|
|
|
+ const anotherID = this.getToken();
|
|
|
+ if (anotherID.type !== this.ruleNames.ID) {
|
|
|
+ throw SyntaxErrorFactory.id_missing(anotherID);
|
|
|
+ }
|
|
|
+ this.pos++;
|
|
|
+ return `${token.text}.${anotherID.text}`;
|
|
|
+ }
|
|
|
this.pos++;
|
|
|
return token.text;
|
|
|
}
|
|
@@ -788,12 +830,12 @@ export class IVProgParser {
|
|
|
parseType () {
|
|
|
const token = this.getToken();
|
|
|
if (
|
|
|
- token.type === this.lexerClass.ID &&
|
|
|
+ token.type === this.ruleNames.ID &&
|
|
|
this.insideScope(IVProgParser.FUNCTION)
|
|
|
) {
|
|
|
return Types.VOID;
|
|
|
} else if (
|
|
|
- token.type === this.lexerClass.RK_VOID &&
|
|
|
+ token.type === this.ruleNames.RK_VOID &&
|
|
|
this.insideScope(IVProgParser.FUNCTION)
|
|
|
) {
|
|
|
this.pos++;
|
|
@@ -801,15 +843,15 @@ export class IVProgParser {
|
|
|
} else if (this.isVariableType(token)) {
|
|
|
this.pos++;
|
|
|
switch (token.type) {
|
|
|
- case this.lexerClass.RK_INTEGER:
|
|
|
+ case this.ruleNames.RK_INTEGER:
|
|
|
return Types.INTEGER;
|
|
|
- case this.lexerClass.RK_BOOLEAN:
|
|
|
+ case this.ruleNames.RK_BOOLEAN:
|
|
|
return Types.BOOLEAN;
|
|
|
- case this.lexerClass.RK_REAL:
|
|
|
+ case this.ruleNames.RK_REAL:
|
|
|
return Types.REAL;
|
|
|
- case this.lexerClass.RK_STRING:
|
|
|
+ case this.ruleNames.RK_STRING:
|
|
|
return Types.STRING;
|
|
|
- case this.lexerClass.RK_CHARACTER:
|
|
|
+ case this.ruleNames.RK_CHARACTER:
|
|
|
return Types.CHAR;
|
|
|
default:
|
|
|
break;
|
|
@@ -867,35 +909,40 @@ export class IVProgParser {
|
|
|
this.checkEOS();
|
|
|
this.pos++;
|
|
|
return cmd;
|
|
|
- } else if (token.type === this.lexerClass.ID) {
|
|
|
- return this.parseIDCommand();
|
|
|
- } else if (token.type === this.lexerClass.LIB_ID) {
|
|
|
+ } else if (token.type === this.ruleNames.ID) {
|
|
|
return this.parseIDCommand();
|
|
|
- } else if (token.type === this.lexerClass.RK_RETURN) {
|
|
|
+ } else if (token.type === this.ruleNames.DOT) {
|
|
|
+ // TODO Check if this is relevant since DOT is a replacement for antlr4 LIB_ID :=> ID . ID
|
|
|
+ throw SyntaxErrorFactory.invalid_syntax(
|
|
|
+ token.text,
|
|
|
+ token.line,
|
|
|
+ token.col
|
|
|
+ );
|
|
|
+ } else if (token.type === this.ruleNames.RK_RETURN) {
|
|
|
return this.parseReturn();
|
|
|
} else if (
|
|
|
- token.type === this.lexerClass.RK_WHILE ||
|
|
|
- token.type === this.lexerClass.RK_WHILE_ALT
|
|
|
+ token.type === this.ruleNames.RK_WHILE ||
|
|
|
+ token.type === this.ruleNames.RK_WHILE_ALT
|
|
|
) {
|
|
|
return this.parseWhile();
|
|
|
} else if (
|
|
|
- token.type === this.lexerClass.RK_FOR ||
|
|
|
- token.type === this.lexerClass.RK_FOR_ALT
|
|
|
+ token.type === this.ruleNames.RK_FOR ||
|
|
|
+ token.type === this.ruleNames.RK_FOR_ALT
|
|
|
) {
|
|
|
return this.parseFor();
|
|
|
- } else if (token.type === this.lexerClass.RK_BREAK) {
|
|
|
+ } else if (token.type === this.ruleNames.RK_BREAK) {
|
|
|
if (!this.insideScope(IVProgParser.BREAKABLE)) {
|
|
|
throw SyntaxErrorFactory.invalid_break_command(
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_BREAK],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_BREAK],
|
|
|
token
|
|
|
);
|
|
|
}
|
|
|
return this.parseBreak();
|
|
|
- } else if (token.type === this.lexerClass.RK_SWITCH) {
|
|
|
+ } else if (token.type === this.ruleNames.RK_SWITCH) {
|
|
|
return this.parseSwitchCase();
|
|
|
- } else if (token.type === this.lexerClass.RK_DO) {
|
|
|
+ } else if (token.type === this.ruleNames.RK_DO) {
|
|
|
return this.parseRepeatUntil();
|
|
|
- } else if (token.type === this.lexerClass.RK_IF) {
|
|
|
+ } else if (token.type === this.ruleNames.RK_IF) {
|
|
|
return this.parseIfThenElse();
|
|
|
} else if (this.checkEOS(true)) {
|
|
|
this.pos++;
|
|
@@ -936,9 +983,9 @@ export class IVProgParser {
|
|
|
const commandsBlock = this.parseCommandBlock();
|
|
|
this.consumeNewLines(); //Maybe not...
|
|
|
const whileToken = this.getToken();
|
|
|
- if (whileToken.type !== this.lexerClass.RK_DO_UNTIL) {
|
|
|
+ if (whileToken.type !== this.ruleNames.RK_DO_UNTIL) {
|
|
|
throw SyntaxErrorFactory.token_missing_one(
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_DO_UNTIL],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_DO_UNTIL],
|
|
|
whileToken
|
|
|
);
|
|
|
}
|
|
@@ -974,18 +1021,18 @@ export class IVProgParser {
|
|
|
const cmdBlocks = this.parseCommandBlock();
|
|
|
|
|
|
const maybeElse = this.getToken();
|
|
|
- if (maybeElse.type === this.lexerClass.RK_ELSE) {
|
|
|
+ if (maybeElse.type === this.ruleNames.RK_ELSE) {
|
|
|
this.pos++;
|
|
|
this.consumeNewLines();
|
|
|
const maybeIf = this.getToken();
|
|
|
let elseBlock = null;
|
|
|
if (this.checkOpenCurly(true)) {
|
|
|
elseBlock = this.parseCommandBlock();
|
|
|
- } else if (maybeIf.type === this.lexerClass.RK_IF) {
|
|
|
+ } else if (maybeIf.type === this.ruleNames.RK_IF) {
|
|
|
elseBlock = this.parseIfThenElse();
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.token_missing_list(
|
|
|
- [this.lexer.literalNames[this.lexerClass.RK_IF], "{"],
|
|
|
+ [this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_IF], "{"],
|
|
|
maybeIf
|
|
|
);
|
|
|
}
|
|
@@ -1015,9 +1062,9 @@ export class IVProgParser {
|
|
|
const for_id = new Expressions.VariableLiteral(id);
|
|
|
for_id.sourceInfo = SourceInfo.createSourceInfo(id_token);
|
|
|
// END parse ID
|
|
|
- const for_from = this.parseForParameters(this.lexerClass.RK_FOR_FROM);
|
|
|
- const for_to = this.parseForParameters(this.lexerClass.RK_FOR_TO);
|
|
|
- const maybePass = this.parseForParameters(this.lexerClass.RK_FOR_PASS);
|
|
|
+ const for_from = this.parseForParameters(this.ruleNames.RK_FOR_FROM);
|
|
|
+ const for_to = this.parseForParameters(this.ruleNames.RK_FOR_TO);
|
|
|
+ const maybePass = this.parseForParameters(this.ruleNames.RK_FOR_PASS);
|
|
|
this.consumeNewLines();
|
|
|
const commandsBlock = this.parseCommandBlock();
|
|
|
this.popScope();
|
|
@@ -1074,8 +1121,8 @@ export class IVProgParser {
|
|
|
|
|
|
parseIDCommand () {
|
|
|
const refToken = this.getToken();
|
|
|
- const isID = refToken.type === this.lexerClass.ID;
|
|
|
const id = this.parseMaybeLibID();
|
|
|
+ const isID = id.indexOf(".") === -1;
|
|
|
if (this.checkOpenBrace(true)) {
|
|
|
this.pos++;
|
|
|
let lineExpression = null;
|
|
@@ -1093,9 +1140,10 @@ export class IVProgParser {
|
|
|
this.checkCloseBrace();
|
|
|
this.pos++;
|
|
|
}
|
|
|
- const equalToken = this.getToken();
|
|
|
- if (equalToken.type !== this.lexerClass.EQUAL) {
|
|
|
- throw SyntaxErrorFactory.token_missing_one("=", equalToken);
|
|
|
+ const assignmentToken = this.getToken();
|
|
|
+ if (assignmentToken.type !== this.ruleNames.ASSIGNMENT) {
|
|
|
+ // TODO BETTER MESSAGE
|
|
|
+ throw SyntaxErrorFactory.token_missing_one("<-", assignmentToken);
|
|
|
}
|
|
|
this.pos++;
|
|
|
const exp = this.parseExpressionOR();
|
|
@@ -1107,27 +1155,29 @@ export class IVProgParser {
|
|
|
columnExpression,
|
|
|
exp
|
|
|
);
|
|
|
- cmd.sourceInfo = SourceInfo.createSourceInfo(equalToken);
|
|
|
+ cmd.sourceInfo = SourceInfo.createSourceInfo(assignmentToken);
|
|
|
return cmd;
|
|
|
}
|
|
|
- const equalOrParenthesis = this.getToken();
|
|
|
- if (isID && equalOrParenthesis.type === this.lexerClass.EQUAL) {
|
|
|
+ const assignmentOrParenthesis = this.getToken();
|
|
|
+ if (isID && assignmentOrParenthesis.type === this.ruleNames.ASSIGNMENT) {
|
|
|
this.pos++;
|
|
|
const exp = this.parseExpressionOR();
|
|
|
this.checkEOS();
|
|
|
this.pos++;
|
|
|
const cmd = new Commands.Assign(id, exp);
|
|
|
- cmd.sourceInfo = SourceInfo.createSourceInfo(equalOrParenthesis);
|
|
|
+ cmd.sourceInfo = SourceInfo.createSourceInfo(assignmentOrParenthesis);
|
|
|
return cmd;
|
|
|
- } else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
|
|
|
+ } else if (
|
|
|
+ assignmentOrParenthesis.type === this.ruleNames.OPEN_PARENTHESIS
|
|
|
+ ) {
|
|
|
const funcCall = this.parseFunctionCallCommand(id);
|
|
|
this.checkEOS();
|
|
|
this.pos++;
|
|
|
return funcCall;
|
|
|
} else if (isID) {
|
|
|
throw SyntaxErrorFactory.token_missing_list(
|
|
|
- ["=", "("],
|
|
|
- equalOrParenthesis
|
|
|
+ ["<-", "("],
|
|
|
+ assignmentOrParenthesis
|
|
|
);
|
|
|
} else {
|
|
|
throw SyntaxErrorFactory.invalid_id_format(refToken);
|
|
@@ -1135,7 +1185,7 @@ export class IVProgParser {
|
|
|
}
|
|
|
|
|
|
parseForParameters (keyword_code) {
|
|
|
- if (keyword_code === this.lexerClass.RK_FOR_PASS) {
|
|
|
+ if (keyword_code === this.ruleNames.RK_FOR_PASS) {
|
|
|
if (this.checkOpenCurly(true)) {
|
|
|
return null;
|
|
|
}
|
|
@@ -1143,7 +1193,7 @@ export class IVProgParser {
|
|
|
const from_token = this.getToken();
|
|
|
if (from_token.type !== keyword_code) {
|
|
|
// TODO better error message
|
|
|
- const keyword = this.lexer.literalNames[keyword_code];
|
|
|
+ const keyword = this.ivprogLexer.getReservedKeys()[keyword_code];
|
|
|
throw new Error(
|
|
|
"Error de sintaxe no comando repita_para: esperava-se " +
|
|
|
keyword +
|
|
@@ -1155,23 +1205,23 @@ export class IVProgParser {
|
|
|
let int_or_id = this.getToken();
|
|
|
let is_unary_op = false;
|
|
|
let op = null;
|
|
|
- if (int_or_id.type === this.lexerClass.SUM_OP) {
|
|
|
+ if (int_or_id.type === this.ruleNames.SUM_OP) {
|
|
|
is_unary_op = true;
|
|
|
op = int_or_id.text;
|
|
|
this.pos += 1;
|
|
|
int_or_id = this.getToken();
|
|
|
}
|
|
|
let for_from = null;
|
|
|
- if (int_or_id.type === this.lexerClass.ID) {
|
|
|
+ if (int_or_id.type === this.ruleNames.ID) {
|
|
|
for_from = new Expressions.VariableLiteral(this.parseID());
|
|
|
for_from.sourceInfo = SourceInfo.createSourceInfo(int_or_id);
|
|
|
- } else if (int_or_id.type === this.lexerClass.INTEGER) {
|
|
|
+ } else if (int_or_id.type === this.ruleNames.INTEGER) {
|
|
|
this.pos += 1;
|
|
|
for_from = this.getIntLiteral(int_or_id);
|
|
|
}
|
|
|
if (for_from == null) {
|
|
|
// TODO better error message
|
|
|
- const keyword = this.lexer.literalNames[keyword_code];
|
|
|
+ const keyword = this.ivprogLexer.getReservedKeys()[keyword_code];
|
|
|
throw new Error(
|
|
|
"Error de sintaxe no comando repeita_para: " +
|
|
|
int_or_id.text +
|
|
@@ -1188,18 +1238,18 @@ export class IVProgParser {
|
|
|
|
|
|
parseCases () {
|
|
|
const token = this.getToken();
|
|
|
- if (token.type !== this.lexerClass.RK_CASE) {
|
|
|
+ if (token.type !== this.ruleNames.RK_CASE) {
|
|
|
throw SyntaxErrorFactory.token_missing_one(
|
|
|
- this.lexer.literalNames[this.lexerClass.RK_CASE],
|
|
|
+ this.ivprogLexer.getReservedKeys()[this.ruleNames.RK_CASE],
|
|
|
token
|
|
|
);
|
|
|
}
|
|
|
this.pos++;
|
|
|
const nextToken = this.getToken();
|
|
|
- if (nextToken.type === this.lexerClass.RK_DEFAULT) {
|
|
|
+ if (nextToken.type === this.ruleNames.RK_DEFAULT) {
|
|
|
this.pos++;
|
|
|
const colonToken = this.getToken();
|
|
|
- if (colonToken.type !== this.lexerClass.COLON) {
|
|
|
+ if (colonToken.type !== this.ruleNames.COLON) {
|
|
|
throw SyntaxErrorFactory.token_missing_one(":", colonToken);
|
|
|
}
|
|
|
this.pos++;
|
|
@@ -1211,7 +1261,7 @@ export class IVProgParser {
|
|
|
} else {
|
|
|
const exp = this.parseExpressionOR();
|
|
|
const colonToken = this.getToken();
|
|
|
- if (colonToken.type !== this.lexerClass.COLON) {
|
|
|
+ if (colonToken.type !== this.ruleNames.COLON) {
|
|
|
throw SyntaxErrorFactory.token_missing_one(":", colonToken);
|
|
|
}
|
|
|
this.pos++;
|
|
@@ -1220,7 +1270,7 @@ export class IVProgParser {
|
|
|
const aCase = new Commands.Case(exp);
|
|
|
aCase.setCommands(block.commands);
|
|
|
const caseToken = this.getToken();
|
|
|
- if (caseToken.type === this.lexerClass.RK_CASE) {
|
|
|
+ if (caseToken.type === this.ruleNames.RK_CASE) {
|
|
|
return [aCase].concat(this.parseCases());
|
|
|
} else {
|
|
|
return [aCase];
|
|
@@ -1233,21 +1283,21 @@ export class IVProgParser {
|
|
|
*
|
|
|
* EOR => EAnd ( 'or' EOR)? #expression and
|
|
|
*
|
|
|
- * EOR => ENot ('and' EOR)? #expression or
|
|
|
+ * EAnd => ENot ('and' EAnd)? #expression or
|
|
|
*
|
|
|
* ENot => 'not'? ER #expression not
|
|
|
*
|
|
|
- * ER => E ((>=, <=, ==, >, <) E)? #expression relational
|
|
|
+ * ER => E ((>=, <=, ==, >, <) ER)? #expression relational
|
|
|
*
|
|
|
* E => factor ((+, -) E)? #expression
|
|
|
*
|
|
|
* factor=> term ((*, /, %) factor)?
|
|
|
*
|
|
|
- * term => literal || arrayAccess || FuncCall || ID || '('EAnd')'
|
|
|
+ * term => literal || arrayAccess || FuncCall || ID || '('EOR')'
|
|
|
**/
|
|
|
parseExpressionOR () {
|
|
|
let exp1 = this.parseExpressionAND();
|
|
|
- while (this.getToken().type === this.lexerClass.OR_OPERATOR) {
|
|
|
+ while (this.getToken().type === this.ruleNames.OR_OPERATOR) {
|
|
|
const opToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const or = convertFromString("or");
|
|
@@ -1262,7 +1312,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseExpressionAND () {
|
|
|
let exp1 = this.parseExpressionNot();
|
|
|
- while (this.getToken().type === this.lexerClass.AND_OPERATOR) {
|
|
|
+ while (this.getToken().type === this.ruleNames.AND_OPERATOR) {
|
|
|
const opToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const and = convertFromString("and");
|
|
@@ -1277,7 +1327,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseExpressionNot () {
|
|
|
const maybeNotToken = this.getToken();
|
|
|
- if (maybeNotToken.type === this.lexerClass.NOT_OPERATOR) {
|
|
|
+ if (maybeNotToken.type === this.ruleNames.NOT_OPERATOR) {
|
|
|
const opToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const not = convertFromString("not");
|
|
@@ -1292,7 +1342,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseExpressionRel () {
|
|
|
let exp1 = this.parseExpression();
|
|
|
- while (this.getToken().type === this.lexerClass.RELATIONAL_OPERATOR) {
|
|
|
+ while (this.getToken().type === this.ruleNames.RELATIONAL_OPERATOR) {
|
|
|
const relToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const rel = convertFromString(relToken.text);
|
|
@@ -1306,7 +1356,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseExpression () {
|
|
|
let factor = this.parseFactor();
|
|
|
- while (this.getToken().type === this.lexerClass.SUM_OP) {
|
|
|
+ while (this.getToken().type === this.ruleNames.SUM_OP) {
|
|
|
const sumOpToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const op = convertFromString(sumOpToken.text);
|
|
@@ -1320,7 +1370,7 @@ export class IVProgParser {
|
|
|
|
|
|
parseFactor () {
|
|
|
let term = this.parseTerm();
|
|
|
- while (this.getToken().type === this.lexerClass.MULTI_OP) {
|
|
|
+ while (this.getToken().type === this.ruleNames.MULTI_OP) {
|
|
|
const multOpToken = this.getToken();
|
|
|
this.pos++;
|
|
|
const op = convertFromString(multOpToken.text);
|
|
@@ -1337,7 +1387,7 @@ export class IVProgParser {
|
|
|
let sourceInfo = null;
|
|
|
let exp = null;
|
|
|
switch (token.type) {
|
|
|
- case this.lexerClass.SUM_OP:
|
|
|
+ case this.ruleNames.SUM_OP:
|
|
|
this.pos++;
|
|
|
sourceInfo = SourceInfo.createSourceInfo(token);
|
|
|
exp = new Expressions.UnaryApp(
|
|
@@ -1346,30 +1396,29 @@ export class IVProgParser {
|
|
|
);
|
|
|
exp.sourceInfo = sourceInfo;
|
|
|
return exp;
|
|
|
- case this.lexerClass.INTEGER:
|
|
|
+ case this.ruleNames.INTEGER:
|
|
|
this.pos++;
|
|
|
return this.getIntLiteral(token);
|
|
|
- case this.lexerClass.REAL:
|
|
|
+ case this.ruleNames.REAL:
|
|
|
this.pos++;
|
|
|
return this.getRealLiteral(token);
|
|
|
- case this.lexerClass.STRING:
|
|
|
+ case this.ruleNames.STRING:
|
|
|
this.pos++;
|
|
|
return this.getStringLiteral(token);
|
|
|
- case this.lexerClass.CHARACTER:
|
|
|
+ case this.ruleNames.CHARACTER:
|
|
|
this.pos++;
|
|
|
return this.getCharLiteral(token);
|
|
|
- case this.lexerClass.RK_TRUE:
|
|
|
- case this.lexerClass.RK_FALSE:
|
|
|
+ case this.ruleNames.RK_TRUE:
|
|
|
+ case this.ruleNames.RK_FALSE:
|
|
|
this.pos++;
|
|
|
return this.getBoolLiteral(token);
|
|
|
- case this.lexerClass.OPEN_CURLY:
|
|
|
+ case this.ruleNames.OPEN_CURLY:
|
|
|
// No more annonymous array
|
|
|
// return this.parseArrayLiteral();
|
|
|
throw SyntaxErrorFactory.annonymous_array_literal(token);
|
|
|
- case this.lexerClass.ID:
|
|
|
- case this.lexerClass.LIB_ID:
|
|
|
+ case this.ruleNames.ID:
|
|
|
return this.parseIDTerm();
|
|
|
- case this.lexerClass.OPEN_PARENTHESIS:
|
|
|
+ case this.ruleNames.OPEN_PARENTHESIS:
|
|
|
return this.parseParenthesisExp();
|
|
|
default:
|
|
|
throw SyntaxErrorFactory.invalid_terminal(token);
|
|
@@ -1379,7 +1428,7 @@ export class IVProgParser {
|
|
|
parseIDTerm () {
|
|
|
const tokenA = this.getToken();
|
|
|
const id = this.parseMaybeLibID();
|
|
|
- const isID = tokenA.type === this.lexerClass.ID;
|
|
|
+ const isID = id.indexOf(".") === -1;
|
|
|
if (isID && this.checkOpenBrace(true)) {
|
|
|
let tokenB = null;
|
|
|
this.pos++;
|
|
@@ -1426,7 +1475,8 @@ export class IVProgParser {
|
|
|
}
|
|
|
|
|
|
parseFunctionCallExpression (id) {
|
|
|
- const tokenA = this.getToken(this.pos - 1);
|
|
|
+ const stepBack = id.indexOf(".") === -1 ? 1 : 3;
|
|
|
+ const tokenA = this.getToken(this.pos - stepBack);
|
|
|
const actualParameters = this.parseActualParameters();
|
|
|
const tokenB = this.getToken(this.pos - 1);
|
|
|
const funcName = this.getFunctionName(id);
|
|
@@ -1443,7 +1493,6 @@ export class IVProgParser {
|
|
|
parseParenthesisExp () {
|
|
|
this.checkOpenParenthesis();
|
|
|
const tokenA = this.getToken();
|
|
|
- this.pos += 1;
|
|
|
this.consumeNewLines();
|
|
|
const exp = this.parseExpressionOR();
|
|
|
this.consumeNewLines();
|
|
@@ -1476,7 +1525,7 @@ export class IVProgParser {
|
|
|
const exp = this.parseExpressionOR();
|
|
|
list.push(exp);
|
|
|
const maybeToken = this.getToken();
|
|
|
- if (maybeToken.type !== this.lexerClass.COMMA) {
|
|
|
+ if (maybeToken.type !== this.ruleNames.COMMA) {
|
|
|
break;
|
|
|
} else {
|
|
|
this.pos++;
|