diff --git a/-15 export issue b/-15 export issue new file mode 100644 index 0000000..0bbada9 --- /dev/null +++ b/-15 export issue @@ -0,0 +1,238 @@ + + SSUUMMMMAARRYY OOFF LLEESSSS CCOOMMMMAANNDDSS + + Commands marked with * may be preceded by a number, _N. + Notes in parentheses indicate the behavior if _N is given. + A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K. + + h H Display this help. + q :q Q :Q ZZ Exit. + --------------------------------------------------------------------------- + + MMOOVVIINNGG + + e ^E j ^N CR * Forward one line (or _N lines). + y ^Y k ^K ^P * Backward one line (or _N lines). + f ^F ^V SPACE * Forward one window (or _N lines). + b ^B ESC-v * Backward one window (or _N lines). + z * Forward one window (and set window to _N). + w * Backward one window (and set window to _N). + ESC-SPACE * Forward one window, but don't stop at end-of-file. + d ^D * Forward one half-window (and set half-window to _N). + u ^U * Backward one half-window (and set half-window to _N). + ESC-) RightArrow * Right one half screen width (or _N positions). + ESC-( LeftArrow * Left one half screen width (or _N positions). + ESC-} ^RightArrow Right to last column displayed. + ESC-{ ^LeftArrow Left to first column. + F Forward forever; like "tail -f". + ESC-F Like F but stop when search pattern is found. + r ^R ^L Repaint screen. + R Repaint screen, discarding buffered input. + --------------------------------------------------- + Default "window" is the screen height. + Default "half-window" is half of the screen height. + --------------------------------------------------------------------------- + + SSEEAARRCCHHIINNGG + + /_p_a_t_t_e_r_n * Search forward for (_N-th) matching line. + ?_p_a_t_t_e_r_n * Search backward for (_N-th) matching line. + n * Repeat previous search (for _N-th occurrence). + N * Repeat previous search in reverse direction. + ESC-n * Repeat previous search, spanning files. + ESC-N * Repeat previous search, reverse dir. & spanning files. + ESC-u Undo (toggle) search highlighting. + &_p_a_t_t_e_r_n * Display only matching lines + --------------------------------------------------- + A search pattern may be preceded by one or more of: + ^N or ! Search for NON-matching lines. + ^E or * Search multiple files (pass thru END OF FILE). + ^F or @ Start search at FIRST file (for /) or last file (for ?). + ^K Highlight matches, but don't move (KEEP position). + ^R Don't use REGULAR EXPRESSIONS. + --------------------------------------------------------------------------- + + JJUUMMPPIINNGG + + g < ESC-< * Go to first line in file (or line _N). + G > ESC-> * Go to last line in file (or line _N). + p % * Go to beginning of file (or _N percent into file). + t * Go to the (_N-th) next tag. + T * Go to the (_N-th) previous tag. + { ( [ * Find close bracket } ) ]. + } ) ] * Find open bracket { ( [. + ESC-^F _<_c_1_> _<_c_2_> * Find close bracket _<_c_2_>. + ESC-^B _<_c_1_> _<_c_2_> * Find open bracket _<_c_1_> + --------------------------------------------------- + Each "find close bracket" command goes forward to the close bracket + matching the (_N-th) open bracket in the top line. + Each "find open bracket" command goes backward to the open bracket + matching the (_N-th) close bracket in the bottom line. + + m_<_l_e_t_t_e_r_> Mark the current top line with . + M_<_l_e_t_t_e_r_> Mark the current bottom line with . + '_<_l_e_t_t_e_r_> Go to a previously marked position. + '' Go to the previous position. + ^X^X Same as '. + ESC-M_<_l_e_t_t_e_r_> Clear a mark. + --------------------------------------------------- + A mark is any upper-case or lower-case letter. + Certain marks are predefined: + ^ means beginning of the file + $ means end of the file + --------------------------------------------------------------------------- + + CCHHAANNGGIINNGG FFIILLEESS + + :e [_f_i_l_e] Examine a new file. + ^X^V Same as :e. + :n * Examine the (_N-th) next file from the command line. + :p * Examine the (_N-th) previous file from the command line. + :x * Examine the first (or _N-th) file from the command line. + :d Delete the current file from the command line list. + = ^G :f Print current file name. + --------------------------------------------------------------------------- + + MMIISSCCEELLLLAANNEEOOUUSS CCOOMMMMAANNDDSS + + -_<_f_l_a_g_> Toggle a command line option [see OPTIONS below]. + --_<_n_a_m_e_> Toggle a command line option, by name. + __<_f_l_a_g_> Display the setting of a command line option. + ___<_n_a_m_e_> Display the setting of an option, by name. + +_c_m_d Execute the less cmd each time a new file is examined. + + !_c_o_m_m_a_n_d Execute the shell command with $SHELL. + |XX_c_o_m_m_a_n_d Pipe file between current pos & mark XX to shell command. + s _f_i_l_e Save input to a file. + v Edit the current file with $VISUAL or $EDITOR. + V Print version number of "less". + --------------------------------------------------------------------------- + + OOPPTTIIOONNSS + + Most options may be changed either on the command line, + or from within less by using the - or -- command. + Options may be given in one of two forms: either a single + character preceded by a -, or a name preceded by --. + + -? ........ --help + Display help (from command line). + -a ........ --search-skip-screen + Search skips current screen. + -A ........ --SEARCH-SKIP-SCREEN + Search starts just after target line. + -b [_N] .... --buffers=[_N] + Number of buffers. + -B ........ --auto-buffers + Don't automatically allocate buffers for pipes. + -c ........ --clear-screen + Repaint by clearing rather than scrolling. + -d ........ --dumb + Dumb terminal. + -D [_x_n_._n] . --color=_x_n_._n + Set screen colors. (MS-DOS only) + -e -E .... --quit-at-eof --QUIT-AT-EOF + Quit at end of file. + -f ........ --force + Force open non-regular files. + -F ........ --quit-if-one-screen + Quit if entire file fits on first screen. + -g ........ --hilite-search + Highlight only last match for searches. + -G ........ --HILITE-SEARCH + Don't highlight any matches for searches. + -h [_N] .... --max-back-scroll=[_N] + Backward scroll limit. + -i ........ --ignore-case + Ignore case in searches that do not contain uppercase. + -I ........ --IGNORE-CASE + Ignore case in all searches. + -j [_N] .... --jump-target=[_N] + Screen position of target lines. + -J ........ --status-column + Display a status column at left edge of screen. + -k [_f_i_l_e] . --lesskey-file=[_f_i_l_e] + Use a lesskey file. + -K --quit-on-intr + Exit less in response to ctrl-C. + -L ........ --no-lessopen + Ignore the LESSOPEN environment variable. + -m -M .... --long-prompt --LONG-PROMPT + Set prompt style. + -n -N .... --line-numbers --LINE-NUMBERS + Don't use line numbers. + -o [_f_i_l_e] . --log-file=[_f_i_l_e] + Copy to log file (standard input only). + -O [_f_i_l_e] . --LOG-FILE=[_f_i_l_e] + Copy to log file (unconditionally overwrite). + -p [_p_a_t_t_e_r_n] --pattern=[_p_a_t_t_e_r_n] + Start at pattern (from command line). + -P [_p_r_o_m_p_t] --prompt=[_p_r_o_m_p_t] + Define new prompt. + -q -Q .... --quiet --QUIET --silent --SILENT + Quiet the terminal bell. + -r -R .... --raw-control-chars --RAW-CONTROL-CHARS + Output "raw" control characters. + -s ........ --squeeze-blank-lines + Squeeze multiple blank lines. + -S ........ --chop-long-lines + Chop (truncate) long lines rather than wrapping. + -t [_t_a_g] .. --tag=[_t_a_g] + Find a tag. + -T [_t_a_g_s_f_i_l_e] --tag-file=[_t_a_g_s_f_i_l_e] + Use an alternate tags file. + -u -U .... --underline-special --UNDERLINE-SPECIAL + Change handling of backspaces. + -V ........ --version + Display the version number of "less". + -w ........ --hilite-unread + Highlight first new line after forward-screen. + -W ........ --HILITE-UNREAD + Highlight first new line after any forward movement. + -x [_N[,...]] --tabs=[_N[,...]] + Set tab stops. + -X ........ --no-init + Don't use termcap init/deinit strings. + -y [_N] .... --max-forw-scroll=[_N] + Forward scroll limit. + -z [_N] .... --window=[_N] + Set size of window. + -" [_c[_c]] . --quotes=[_c[_c]] + Set shell quote characters. + -~ ........ --tilde + Don't display tildes after end of file. + -# [_N] .... --shift=[_N] + Horizontal scroll amount (0 = one half screen width) + ........ --no-keypad + Don't send termcap keypad init/deinit strings. + ........ --follow-name + The F command changes files if the input file is renamed. + ........ --use-backslash + Subsequent options use backslash as escape char. + + + --------------------------------------------------------------------------- + + LLIINNEE EEDDIITTIINNGG + + These keys can be used to edit text being entered + on the "command line" at the bottom of the screen. + + RightArrow ..................... ESC-l ... Move cursor right one character. + LeftArrow ...................... ESC-h ... Move cursor left one character. + ctrl-RightArrow ESC-RightArrow ESC-w ... Move cursor right one word. + ctrl-LeftArrow ESC-LeftArrow ESC-b ... Move cursor left one word. + HOME ........................... ESC-0 ... Move cursor to start of line. + END ............................ ESC-$ ... Move cursor to end of line. + BACKSPACE ................................ Delete char to left of cursor. + DELETE ......................... ESC-x ... Delete char under cursor. + ctrl-BACKSPACE ESC-BACKSPACE ........... Delete word to left of cursor. + ctrl-DELETE .... ESC-DELETE .... ESC-X ... Delete word under cursor. + ctrl-U ......... ESC (MS-DOS only) ....... Delete entire line. + UpArrow ........................ ESC-k ... Retrieve previous command line. + DownArrow ...................... ESC-j ... Retrieve next command line. + TAB ...................................... Complete filename & cycle. + SHIFT-TAB ...................... ESC-TAB Complete filename & reverse cycle. + ctrl-L ................................... Complete filename, list all. + + diff --git a/build.gradle b/build.gradle index 166be09..6f0ed32 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ plugins { } group 'cafe' -version '0.4.1' +version '0.4.2' sourceCompatibility = '1.8' targetCompatibility = '1.8' diff --git a/src/main/java/compiler/ir/DeclarativeAssignmentStatement.java b/src/main/java/compiler/ir/DeclarativeAssignmentStatement.java index 5db217f..a6809a1 100644 --- a/src/main/java/compiler/ir/DeclarativeAssignmentStatement.java +++ b/src/main/java/compiler/ir/DeclarativeAssignmentStatement.java @@ -64,6 +64,10 @@ public SymbolReference getSymbolReference() { return symbolReference; } + @Override + public String getName(){ + return symbolReference.getName(); + } @Override public List> children() { return Collections.singletonList(expressionStatement); diff --git a/src/main/java/compiler/ir/ExpressionStatement.java b/src/main/java/compiler/ir/ExpressionStatement.java index 3070e27..16dd727 100644 --- a/src/main/java/compiler/ir/ExpressionStatement.java +++ b/src/main/java/compiler/ir/ExpressionStatement.java @@ -38,4 +38,7 @@ public static ExpressionStatement of(Object expr) { throw cantConvert("ExpressionStatement", expr); } + public String getName(){ + return null; + } } diff --git a/src/main/java/compiler/ir/FunctionInvocation.java b/src/main/java/compiler/ir/FunctionInvocation.java index da0dfd6..a59d9d4 100644 --- a/src/main/java/compiler/ir/FunctionInvocation.java +++ b/src/main/java/compiler/ir/FunctionInvocation.java @@ -47,7 +47,7 @@ public ExpressionStatement getReference() { return ref; } - public static FunctionInvocation create(Object ref, List args) { + public static FunctionInvocation create(Object ref, List> args) { List> arguments = new LinkedList<>(); for (Object arg : args) { if (arg instanceof CafeElement) { diff --git a/src/main/java/compiler/ir/MethodInvocation.java b/src/main/java/compiler/ir/MethodInvocation.java index 44a5e42..90b802c 100644 --- a/src/main/java/compiler/ir/MethodInvocation.java +++ b/src/main/java/compiler/ir/MethodInvocation.java @@ -41,7 +41,7 @@ private MethodInvocation(ExpressionStatement invokedUpon, List this.arguments = arguments; } - public static MethodInvocation create(Object invokedOn, List args) { + public static MethodInvocation create(Object invokedOn, List> args) { List> arguments = new LinkedList<>(); for (Object arg : args) { if (arg instanceof CafeElement) { diff --git a/src/main/java/compiler/ir/OperatorType.java b/src/main/java/compiler/ir/OperatorType.java index 3d1cf1a..042a99a 100644 --- a/src/main/java/compiler/ir/OperatorType.java +++ b/src/main/java/compiler/ir/OperatorType.java @@ -38,6 +38,7 @@ public enum OperatorType { TIMES("*"), DIVIDE("/"), MODULO("%"), + TILDE("~"), POW("**"), FLOOR("//"), diff --git a/src/main/java/compiler/ir/PropertyAccess.java b/src/main/java/compiler/ir/PropertyAccess.java index 76526c4..4de3388 100644 --- a/src/main/java/compiler/ir/PropertyAccess.java +++ b/src/main/java/compiler/ir/PropertyAccess.java @@ -29,8 +29,16 @@ package compiler.ir; +import compiler.parser.Tokens; +import compiler.util.Position; + public class PropertyAccess extends ExpressionStatement { private String name; + private Tokens.Token firstToken; + + public void setFirstToken(Tokens.Token firstToken) { + this.firstToken = firstToken; + } private PropertyAccess(String name) { this.name = name; diff --git a/src/main/java/compiler/ir/ReferenceLookup.java b/src/main/java/compiler/ir/ReferenceLookup.java index ab1232c..8d84123 100644 --- a/src/main/java/compiler/ir/ReferenceLookup.java +++ b/src/main/java/compiler/ir/ReferenceLookup.java @@ -29,10 +29,17 @@ package compiler.ir; +import compiler.parser.Tokens; +import compiler.util.Position; + public class ReferenceLookup extends ExpressionStatement { private final String name; + private Tokens.Token firstToken; + public void setFirstToken(Tokens.Token firstToken) { + this.firstToken = firstToken; + } public ReferenceLookup(String name) { this.name = name; } diff --git a/src/main/java/compiler/main/CafeCompiler.java b/src/main/java/compiler/main/CafeCompiler.java index 4bff4a1..c289778 100644 --- a/src/main/java/compiler/main/CafeCompiler.java +++ b/src/main/java/compiler/main/CafeCompiler.java @@ -31,8 +31,6 @@ import compiler.analyzer.SemanticsChecker; import compiler.ast.Node; -import compiler.ast.Node.ProgramNode; -import compiler.gen.ASTToCafeIrVisitor; import compiler.gen.ClosureReferenceVisitor; import compiler.gen.JVMByteCodeGenVisitor; import compiler.gen.SymbolReferenceAssignmentVisitor; @@ -86,8 +84,8 @@ public CafeCompiler(String sourceFile) { enum Phase { INIT, PARSE, - ANALYZE, IR, + // ANALYZE, GEN } @@ -115,16 +113,17 @@ public CompilerResult compile() { fileManager.setSourceFile(sourceFile); break; case PARSE: - parser = parserFactory.newParser(ParserType.MAINPARSER, fileManager.asCharList()); - programNode = parser.parse(); - break; - case ANALYZE: -// System.out.println((char) 27 + "[33m" + "\nPrettyPrint"); -// new PrettyPrinter().prettyPrint(programNode); - analyzer.visitProgram((ProgramNode) programNode); + parser = parserFactory.newParser(ParserType.IRParser, fileManager.asCharList()); + module = parser.parse(moduleName); + System.out.println("Success " + module); break; +// case ANALYZE: +//// System.out.println((char) 27 + "[33m" + "\nPrettyPrint"); +//// new PrettyPrinter().prettyPrint(programNode); +//// analyzer.visitProgram((ProgramNode) programNode); +// break; case IR: - module = new ASTToCafeIrVisitor().transform((ProgramNode) programNode, moduleName); +// module = new ASTToCafeIrVisitor().transform((ProgramNode) programNode, moduleName); module.accept(new ClosureReferenceVisitor()); module.accept(new SymbolReferenceAssignmentVisitor()); break; diff --git a/src/main/java/compiler/parser/MainParser.java b/src/main/java/compiler/parser/ASTParser.java similarity index 99% rename from src/main/java/compiler/parser/MainParser.java rename to src/main/java/compiler/parser/ASTParser.java index d0922d3..abea66a 100644 --- a/src/main/java/compiler/parser/MainParser.java +++ b/src/main/java/compiler/parser/ASTParser.java @@ -43,9 +43,9 @@ import static compiler.util.Log.Type.*; import static compiler.util.Messages.message; -public class MainParser extends Parser { +public class ASTParser extends Parser { static { - ParserFactory.registerParser(ParserType.MAINPARSER, new MainParser()); + ParserFactory.registerParser(ParserType.ASTParser, new ASTParser()); } private Lexer lexer; @@ -54,10 +54,10 @@ public class MainParser extends Parser { private boolean breakAllowed = false, innerLoop = false, error = false; private List debug = new ArrayList<>(); - private MainParser() { + private ASTParser() { } - private MainParser(ParserFactory factory, Lexer lexer) { + private ASTParser(ParserFactory factory, Lexer lexer) { debug.add("PARSING"); this.lexer = lexer; this.log = factory.log; @@ -72,8 +72,8 @@ private MainParser(ParserFactory factory, Lexer lexer) { } @Override - protected MainParser instance(ParserFactory factory, Lexer lexer) { - return new MainParser(factory, lexer); + protected ASTParser instance(ParserFactory factory, Lexer lexer) { + return new ASTParser(factory, lexer); } Token token() { @@ -2002,7 +2002,7 @@ ProgramNode parseProgram() { } @Override - public Node parse() { + public Node parse(String moduleName) { // while(token.kind != TokenKind.END) { // if(token.kind == TokenKind.ERROR) { // return; diff --git a/src/main/java/compiler/parser/IRParser.java b/src/main/java/compiler/parser/IRParser.java new file mode 100644 index 0000000..1e507aa --- /dev/null +++ b/src/main/java/compiler/parser/IRParser.java @@ -0,0 +1,2008 @@ +/* + * Copyright (c) 2021. Dhyey Shah, Saurabh Pethani, Romil Nisar + * + * Developed by: + * Dhyey Shah + * https://github.com/dhyey-shah + * + * Contributors: + * Saurabh Pethani + * https://github.com/SaurabhPethani + * + * Romil Nisar + * + * + * This file is part of Cafe. + * + * Cafe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * Cafe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cafe. If not, see . + */ + +package compiler.parser; + +import compiler.ast.Node; +import compiler.ast.Node.ContinueStmtNode; +import compiler.ast.Node.IdenNode; +import compiler.ast.Node.Tag; +import compiler.gen.AnnFuncNameGenerator; +import compiler.ir.*; +import compiler.parser.Tokens.Token; +import compiler.parser.Tokens.TokenKind; +import compiler.util.Log; +import compiler.util.Position; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.*; + +import static compiler.util.Log.Type.SOURCE_POSITION; +import static compiler.util.Log.Type.SYMBOL_EXPECTED; +import static compiler.util.Messages.message; + +public class IRParser extends Parser { + static { + ParserFactory.registerParser(ParserType.IRParser, new IRParser()); + } + + @Override + public CafeModule parse(String moduleName) { + IRParser.Context.context.createModule(moduleName); + return parseStatements(); + } + + private static final class Context { + final static IRParser.Context context = new IRParser.Context(); + + public CafeModule module; + private final Deque referenceTableStack = new LinkedList<>(); + private final Deque functionStack = new LinkedList<>(); + private final Deque forLoopStack = new LinkedList<>(); + private final AnnFuncNameGenerator annFuncNameGenerator = new AnnFuncNameGenerator(); + + private boolean isModuleScope = true; + + private boolean isProperty = false; + + // for functions to be exported + private boolean isExport = false; + + public void enterProperty() { + isProperty = true; + } + + public void leaveProperty() { + isProperty = false; + } + + public boolean isProperty() { + return isProperty; + } + + private Context() { + } + + public CafeModule createModule(String moduleName) { + ReferenceTable global = new ReferenceTable(); + referenceTableStack.push(global); + module = CafeModule.create(moduleName, global); + return module; + } + + public Block enterScope() { + assert referenceTableStack.peek() != null; + ReferenceTable blockReferenceTable = referenceTableStack.peek() + .fork(); + referenceTableStack.push(blockReferenceTable); + return Block.create(blockReferenceTable); + } + + public void leaveScope() { + referenceTableStack.pop(); + } + + public void enterFunc(String n) { + isModuleScope = false; + functionStack.push(n); + annFuncNameGenerator.enter(); + } + + public void leaveFunc() { + functionStack.pop(); + if (functionStack.size() == 0) + isModuleScope = true; + annFuncNameGenerator.leave(); + } + + public String getNextAnnFuncName() { + String name = annFuncNameGenerator.current(); + annFuncNameGenerator.next(); + return name; + } + + public enum Scope { + GLOBAL, LOCAL, CLOSURE + } + + public IRParser.Context.Scope currentScope() { + if (functionStack.size() == 0) + return IRParser.Context.Scope.GLOBAL; + if (functionStack.size() == 1) + return IRParser.Context.Scope.LOCAL; + return IRParser.Context.Scope.CLOSURE; + } + + SymbolReference createSymbolReference(String name, SymbolReference.Kind kind, SymbolReference.Scope scope) { + SymbolReference ref = SymbolReference.of(name, kind, scope); + assert referenceTableStack.peek() != null; + referenceTableStack.peek() + .add(ref); + return ref; + } + + public SymbolReference createSymbolReference(String name, Node.Tag tag) { + return createSymbolReference(name, getSymbolKind(tag), getSymbolScope()); + } + + + SymbolReference.Kind getSymbolKind(Node.Tag tag) { + if (tag == Node.Tag.VARDECL) { + return SymbolReference.Kind.VAR; + } else if (tag == Node.Tag.CONSTDECL) { + return SymbolReference.Kind.CONST; + } + throw new AssertionError("Invalid Symbol Kind"); + } + + SymbolReference.Scope getSymbolScope() { + // There can be only 2 visible symbol scopes: GLOBAL & LOCAL. + // A symbol declared inside a closure is LOCAL to that closure & a CLOSURE itself is LOCAL to its parent block. + // So there is no CLOSURE scope for symbols. + IRParser.Context.Scope scope = currentScope(); + if (scope == IRParser.Context.Scope.GLOBAL) + return SymbolReference.Scope.GLOBAL; + if (scope == IRParser.Context.Scope.LOCAL || scope == IRParser.Context.Scope.CLOSURE) + return SymbolReference.Scope.LOCAL; + throw new AssertionError("Invalid Symbol Scope"); + } + + public void addFunction(CafeFunction function) { + context.module.addFunction(function); + } + } + + + + + private Lexer lexer; + private Token token; + private Log log; + private boolean breakAllowed = false; + private boolean error = false; + private List debug = new ArrayList<>(); + + private IRParser() { + } + + private IRParser(ParserFactory factory, Lexer lexer) { + debug.add("PARSING"); + this.lexer = lexer; + this.log = factory.log; + // TESTING + // nextToken(); + // while(token.kind != TokenKind.END) { + // debug.add(token.kind); + // nextToken(); + // if(token.kind == TokenKind.ERROR) + // break; + // } + } + + @Override + protected IRParser instance(ParserFactory factory, Lexer lexer) { + return new IRParser(factory, lexer); + } + + Token prevToken() { + return lexer.prevToken(); + } + + void nextToken() { + if (!error) { + lexer.nextToken(); + token = lexer.token(); + } + } + + private String errorDescription(Position position, String message) { + return message + ' ' + message(SOURCE_POSITION, position.getStartLine(), position.getStartColumn()); + } + + private boolean accept(TokenKind tokenKindExpected) { + if (error) return false; + if (token.kind == TokenKind.ERROR) { + error = true; + return false; + } + if (tokenKindExpected == token.kind) { + nextToken(); + return true; + } else { + logError(tokenKindExpected); + return false; + } + } + + private void logError(TokenKind tokenKindExpected) { + error = true; + log.report(SYMBOL_EXPECTED, token.pos, + errorDescription(token.pos, message(SYMBOL_EXPECTED, tokenKindExpected, token.kind))); + } + + private void logError(Object... values) { + error = true; + log.report(Log.Type.INVALID_EXPRESSION, token.pos, + errorDescription(token.pos, message(Log.Type.INVALID_EXPRESSION, values))); + + } + + ExpressionStatement parseLogicalOrExpression() { + /* + * parseLogicalAndExpression() while(TokenType == OR | TokenType == '||'){ + * parseLogicalAndExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseLogicalAndExpression(); + while (token.kind == TokenKind.OROP || token.kind == TokenKind.OR) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseLogicalAndExpression(); +// exp1 = new BinaryExprNode(exp1, exp2, op); + exp1 = BinaryExpression.of(OperatorType.OR) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + + } + + ExpressionStatement parseLogicalAndExpression() { + /* + * parseLogicalNotExpression() while(TokenType == AND | TokenType == '&&'){ + * parseLogicalNotExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseLogicalNotExpression(); + while (token.kind == TokenKind.ANDOP || token.kind == TokenKind.AND) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseLogicalNotExpression(); + exp1 = BinaryExpression.of(OperatorType.AND) + .right(exp2) + .left(exp1); +// exp1 = new BinaryExprNode(exp1, exp2, op); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseLogicalNotExpression() { + /* + * parseNotEqualToExpression() while(TokenType == NOT | TokenType == '!'){ + * parseNotEqualToExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseNotEqualToExpression(); + while (token.kind == TokenKind.NOTOP || token.kind == TokenKind.NOT) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseNotEqualToExpression(); + exp1 = BinaryExpression.of(OperatorType.NOT) + .right(exp2) + .left(exp1); +// exp1 = new BinaryExprNode(exp1, exp2, op); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseNotEqualToExpression() { + /* + * parseEqualEqualExpression() accept(NOT_EQ) while(TokenType == '!='){ + * parseEqualEqualExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseEqualEqualExpression(); + while (token.kind == TokenKind.NOTEQU) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseEqualEqualExpression(); + exp1 = BinaryExpression.of(OperatorType.NOTEQUALS) + .right(exp2) + .left(exp1); +// exp1 = new BinaryExprNode(exp1, exp2, op); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseEqualEqualExpression() { + /* + * parseRealtionalExpression() while(TokenType == '=='){ + * parseRealtionalExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseRelationalExpression(); + while (token.kind == TokenKind.EQUEQU) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseRelationalExpression(); + exp1 = BinaryExpression.of(OperatorType.EQUALS) + .right(exp2) + .left(exp1); +// exp1 = new BinaryExprNode(exp1, exp2, op); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseRelationalExpression() { + /* + * parseBitOrExpression() while(TokenType == <,>,<=,>=,in ,not in, is, is not ){ + * parseBitOrExpression() } + */ + if (error) return null; +// Token tk = token; + ExpressionStatement exp1 = parseBitOrExpression(); + if (exp1 == null) { + error = true; + return null; + } + while (token.kind == TokenKind.LT || token.kind == TokenKind.GT || token.kind == TokenKind.LTE + || token.kind == TokenKind.GTE || token.kind == TokenKind.IN || token.kind == TokenKind.IS + || token.kind == TokenKind.NOT) { + if (error) + return null; + OperatorType op = token.kind == TokenKind.LT ? OperatorType.LESS : token.kind == TokenKind.GT ? OperatorType.MORE : token.kind == TokenKind.LTE ? OperatorType.LESSOREQUALS : token.kind == TokenKind.GTE ? OperatorType.MOREOREQUALS : token.kind == TokenKind.IN ? OperatorType.IN : token.kind == TokenKind.IS ? OperatorType.IS : OperatorType.NOT; + if (token.kind == TokenKind.IS) { + accept(token.kind); + op = OperatorType.IS; + if (token.kind == TokenKind.NOT) { + op = OperatorType.ISNOT; + accept(token.kind); + } + } else if (token.kind == TokenKind.NOT) { + accept(token.kind); + if (token.kind == TokenKind.IN) { + op = OperatorType.NOTIN; + accept(TokenKind.IN); + } + }else{ + accept(token.kind); + } + + ExpressionStatement exp2 = parseBitOrExpression(); + exp1 = BinaryExpression.of(op) + .right(exp2) + .left(exp1); + } + if (error) return null; + + return exp1; + } + + ExpressionStatement parseBitOrExpression() { + /* + * parseBitXorExpression() while(TokenType == '|'){ parseBitXorExpression() } + */ + + if (error) return null; + ExpressionStatement exp1 = parseBitXorExpression(); + while (token.kind == TokenKind.BITOR) { + if (error) + return null; +// String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseBitXorExpression(); + exp1 = BinaryExpression.of(OperatorType.BITOR) + .right(exp2) + .left(exp1); + + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseBitXorExpression() { + /* + * parseLogicalAndExpression() while(TokenType == '^'){ + * parseLogicalAndExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseBitAndExpression(); + while (token.kind == TokenKind.BITAND) { + if (error) + return null; + String op = token.value(); + accept(token.kind); + ExpressionStatement exp2 = parseBitAndExpression(); + exp1 = BinaryExpression.of(op) + .right(exp2) + .left(exp1); +// exp1 = new BinaryExprNode(exp1, exp2, op); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseBitAndExpression() { + /* + * parseBitRightShiftExpression() while(TokenType == '&'){ + * parseBitRightShiftExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseBitRightShiftExpression(); + while (token.kind == TokenKind.ANDOP) { + if (error) + return null; + accept(token.kind); + ExpressionStatement exp2 = parseBitRightShiftExpression(); + exp1 = BinaryExpression.of(OperatorType.AND) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseBitRightShiftExpression() { + /* + * parseBitLeftShiftExpression() while(TokenType == '>>' | TokenType == '>>>'){ + * parseBitLeftShiftExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseBitLeftShiftExpression(); + while (token.kind == TokenKind.RSHIFT || token.kind == TokenKind.TRSHIFT) { + if (error) + return null; + OperatorType op = token.kind == TokenKind.RSHIFT ? OperatorType.BITRIGHTSHIFT_SIGNED : OperatorType.BITRIGHTSHIFT_UNSIGNED; + accept(token.kind); + ExpressionStatement exp2 = parseBitLeftShiftExpression(); + exp1 = BinaryExpression.of(op) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseBitLeftShiftExpression() { + /* + * parseSubtractExpression() while(TokenType == '<<' | TokenType == '<<<'){ + * parseSubtractExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseSubtractExpression(); + while (token.kind == TokenKind.LSHIFT) { + if (error) + return null; + accept(token.kind); + ExpressionStatement exp2 = parseSubtractExpression(); + exp1 = BinaryExpression.of(OperatorType.BITLEFTSHIFT) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseSubtractExpression() { + /* + * parseAdditionExpression() while(TokenType == '-'){ parseAdditionExpression() + * } + */ + if (error) return null; + ExpressionStatement exp1 = parseAdditionExpression(); + while (token.kind == TokenKind.SUB) { + if (error) + return null; + accept(token.kind); + ExpressionStatement exp2 = parseAdditionExpression(); + exp1 = BinaryExpression.of(OperatorType.MINUS) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseAdditionExpression() { + /* + * parseMultiplicationExpression() while(TokenType == '+'){ + * parseMultiplicationExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseMultiplicationExpression(); + while (token.kind == TokenKind.ADD) { + if (error) + return null; + accept(token.kind); + ExpressionStatement exp2 = parseMultiplicationExpression(); + exp1 = BinaryExpression.of(OperatorType.PLUS) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseMultiplicationExpression() { + /* + * parseDivisionExpression() while(TokenType == '*'){ parseDivisionExpression() + * } + */ + if (error) return null; + ExpressionStatement exp1 = parseDivisionExpression(); + while (token.kind == TokenKind.MUL) { + if (error) + return null; + accept(token.kind); + ExpressionStatement exp2 = parseDivisionExpression(); + exp1 = BinaryExpression.of(OperatorType.TIMES) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseDivisionExpression() { + /* + * parseFactorExpression() while(TokenType == /, %, // ){ + * parseFactorExpression() } + */ + if (error) return null; + ExpressionStatement exp1 = parseFactorExpression(); + while (token.kind == TokenKind.DIV || token.kind == TokenKind.MOD || token.kind == TokenKind.FLOORDIV) { + if (error) + return null; + OperatorType op = TokenKind.DIV == token.kind ? OperatorType.DIVIDE : TokenKind.MOD == token.kind ? OperatorType.MODULO : OperatorType.FLOOR; + accept(token.kind); + ExpressionStatement exp2 = parseFactorExpression(); + exp1 = BinaryExpression.of(op) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseFactorExpression() { + /* + * + * if( TokenType == -, ~ ) parseFactorExpression() parsePowerExpression() + * + */ + if (error) return null; + ExpressionStatement exp1; + if (token.kind == TokenKind.SUB || token.kind == TokenKind.TILDE + || token.kind == TokenKind.NOT + || token.kind == TokenKind.NOTOP) { + if (prevToken().kind == TokenKind.IDENTIFIER) { + // Handle Case where previous token is identifier and sould not generate + // UnaryOperator + exp1 = parsePowerExpression(); + } else { + OperatorType op = token.kind == TokenKind.SUB ? OperatorType.MINUS : TokenKind.TILDE == token.kind ? OperatorType.TILDE : TokenKind.NOT == token.kind ? OperatorType.NOT : OperatorType.NOTOP; + accept(token.kind); + exp1 = parsePowerExpression(); + exp1 = UnaryExpression.create(op, exp1); + } + } else { + exp1 = parsePowerExpression(); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parsePowerExpression() { + /* + * parseAtomExpression() while(TokenType == '**'){ parseAtomExpression() } + */ + if (error) return null; + ExpressionStatement exp1, exp2; + try { + exp1 = parseAtomExpression(); + while (token.kind == TokenKind.POWER) { + if (error) + return null; + accept(TokenKind.POWER); + exp2 = parseFactorExpression(); + exp1 = BinaryExpression.of(OperatorType.POW) + .right(exp2) + .left(exp1); + } + if (error) return null; + return exp1; + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + ExpressionStatement parseTrailer(ExpressionStatement oExp) throws ParseException { + ExpressionStatement node = null; + Context context = Context.context; + boolean isProperty = context.isProperty(); + if (token.kind == TokenKind.LPAREN || token.kind == TokenKind.DOT || token.kind == TokenKind.LSQU) { + switch (token.kind) { + case LPAREN: + accept(TokenKind.LPAREN); + +// // eg: a.b() +// // b is a property of a, thus method invocation node is created. + if (context.isProperty()) { + context.leaveProperty(); + node = MethodInvocation.create(oExp, parseArgList()); + } + else { + // eg: a() + // a() is normal function call, thus function invocation node is created. + context.leaveProperty(); + node = FunctionInvocation.create(oExp, parseArgList()); + } + if (isProperty) context.enterProperty(); + accept(TokenKind.RPAREN); + break; + + case LSQU: + ExpressionStatement exp1, exp2; + debug.add("Atom Expr: " + token.kind); + context.leaveProperty(); + while (token.kind == TokenKind.LSQU) { + if (error) + return null; + accept(TokenKind.LSQU); + // if (token.kind == TokenKind.IDENTIFIER) + // exp1 = parseIdentifier(); + // else + // exp1 = parseNumberLiteral(); + exp1 = parseAtomExpression(); + if (token.kind == TokenKind.COLON) { + accept(TokenKind.COLON); + exp2 = parseAtomExpression(); + accept(TokenKind.RSQU); + node = SliceExpression.slice(oExp) + .beginsAt(exp1) + .endsAt(exp2); + } else { + accept(TokenKind.RSQU); + node = SubscriptExpression.create(oExp, exp1); + oExp = node; + } + + } + if (isProperty) context.enterProperty(); + break; + case DOT: + ExpressionStatement e1; + debug.add("Atom DOT:" + oExp); + accept(TokenKind.DOT); + context.enterProperty(); + e1 = parseIdentifier(); + if (error) + return null; + ExpressionStatement trail = e1; + while (token.kind != TokenKind.DOT && (token.kind == TokenKind.LSQU || token.kind == TokenKind.LPAREN)) { + trail = parseTrailer(trail); + } + context.leaveProperty(); + if (trail == null) + node = ObjectAccessStatement.create(oExp, e1); + else + node= ObjectAccessStatement.create(oExp, trail); + debug.add("Token Kind: " + token.kind); + break; + } + } + return node; + } + + ExpressionStatement parseAtomExpression() throws ParseException { + /* + * List of Trailers parseAtom() + * + * trail = parseTrailer() while (trail) trail = parseTrailer() + */ + + if (error) return null; + debug.add("Atom Expr Node Token: " + token.kind); + ExpressionStatement oExp = parseAtom(); + if (oExp == null) { + error = true; + return null; + } + debug.add("Atom Expr Node Token: " + token.kind); + if (oExp instanceof PropertyAccess || oExp instanceof ThisStatement || oExp instanceof ReferenceLookup) { + ExpressionStatement trailer; + while ((trailer = parseTrailer(oExp)) != null) { + oExp = trailer; + } + } + + if (error) return null; + return oExp; + } + + CafeStatement parseExprStmt() { + if (error) return null; + ExpressionStatement exp1 = parseLogicalAndExpression(); + ExpressionStatement exp2; + debug.add("Expr Stmt : " + token.kind); + if (token.kind == TokenKind.OR || token.kind == TokenKind.OROP) { + String op = token.value(); + accept(token.kind); + exp2 = parseLogicalAndExpression(); + exp1 = BinaryExpression.of(op) + .right(exp2) + .left(exp1); + } else if (token.kind == TokenKind.EQU) { + accept(token.kind); + exp2 = parseValue(); + + return AssignmentStatement.create(exp1, exp2); + } + if (error) return null; + return exp1; + } + + ExpressionStatement parseAtom() { + /* + * switch TokenType case LPAREN: parseExpressionStatement exp1 = null; + switch (token.kind) { + case LPAREN: + accept(TokenKind.LPAREN); + exp1 = parseExprStmt(); + accept(TokenKind.RPAREN); + break; + case IDENTIFIER: + exp1 = parseIdentifier(); + break; + case STRLIT: + exp1 = parseStringLiteral(); + break; + case NUMLIT: + try { + exp1 = parseNumberLiteral(); + } catch (ParseException e) { + // TODO Auto-generated catch block + // e.printStackTrace(); + debug.add("Exception Thrown in parseAtom by NUMLIT"); + } + break; + case TRUE: + case FALSE: + exp1 = parseBoolLiteral(); + break; + case NULL: + exp1 = parseNull(); + break; + case THIS: + exp1 = parseThis(); + break; + default: + logError(); + } + if (error) return null; + if (exp1 == null) { + error = true; + return null; + } + return (ExpressionStatement) exp1; + + } + + ExpressionStatement parseNull() { + if (error) return null; + return new NullStatement(); + } + + ExpressionStatement parseThis() { + if (error) return null; + accept(TokenKind.THIS); + IRParser.Context context = IRParser.Context.context; + boolean isGlobal = false; + if (context.isModuleScope) { + isGlobal = true; + } + return ThisStatement.create(isGlobal); + } + + ExpressionStatement parseIdentifier() { + /* + * Create Identifier Node. return IdentNode() + */ + if (error) return null; + Token prev = token; + accept(TokenKind.IDENTIFIER); + IdenNode iden = new IdenNode(prev.value()); + iden.setFirstToken(prev); + IRParser.Context context = IRParser.Context.context; + if (context.isProperty()) { + PropertyAccess prop = PropertyAccess.of(prev.value()); + prop.setFirstToken(prev); + return prop; + }else { + ReferenceLookup refs = ReferenceLookup.of(prev.value()); + refs.setFirstToken(prev); + return refs; + } + } + + ExpressionStatement parseStringLiteral() { + /* + * check Quotes accept(STRING LITERAL) + * + */ + if (error) return null; + Token prev = token; + accept(TokenKind.STRLIT); + return new ConstantStatement(prev.value()); + + } + + ExpressionStatement parseNumberLiteral() throws ParseException { + /* + * + */ + if (error) return null; + Token prevToken = token; + accept(TokenKind.NUMLIT); + Number num, num2; + debug.add("Num Literal PrevToken: " + prevToken.kind); + if (token.kind == TokenKind.DOT) { + nextToken(); + if (token.kind == TokenKind.NUMLIT) { + num = NumberFormat.getInstance() + .parse(prevToken.value() + '.' + token.value()); + accept(TokenKind.NUMLIT); + if (error) return null; + return new ConstantStatement(num); + } else { + accept(TokenKind.NUMLIT); + } + } else { + num = NumberFormat.getInstance() + .parse(prevToken.value()); + if (num instanceof Long) { + if ((long) num <= Integer.MAX_VALUE) { + num2 = num.intValue(); + } else { + num2 = num; + } + } else { + num2 = num; + } + if (error) return null; + return new ConstantStatement(num2); + } + + return null; + } + + ExpressionStatement parseBoolLiteral() { + /* + * + */ + if (error) return null; +// Token tk = token; + if (token.kind == TokenKind.TRUE) { + accept(TokenKind.TRUE); + if (error) return null; + return new ConstantStatement(true); + } else if (token.kind == TokenKind.FALSE) { + accept(TokenKind.FALSE); + if (error) return null; + return new ConstantStatement(false); + } + return null; + } + + List> parseArgList() { + /* + * parseArg() while(COMMA) parseArg() + */ + if (error) return null; + List> args = new ArrayList<>(); + while (token.kind != TokenKind.RPAREN) { + if (error) + return null; + args.add(parseValue()); + if (token.kind != TokenKind.RPAREN) + accept(TokenKind.COMMA); + } + if (error) return null; + return args; + } + + /* parseStatements */ + ConditionalBranching parseIf() { + if (error) return null; + ExpressionStatement ifCond; + Block ifBlock; + nextToken(); + accept(TokenKind.LPAREN); + ifCond = parseLogicalOrExpression(); + if (ifCond == null) { + // log.report(Type.ERROR, token.pos, errorDescription(token.pos, "If without condition!")); + logError(); + error = true; + return null; + } + accept(TokenKind.RPAREN); + accept(TokenKind.LCURLY); + if (token.kind != TokenKind.RCURLY) + ifBlock = parseLoopBlock(); + else + ifBlock = parseBlock(); + + accept(TokenKind.RCURLY); + + if (error) return null; + return ConditionalBranching + .branch() + .condition(ifCond) + .whenTrue(ifBlock); + } + + CafeStatement parseIfStatement() { + /* + * Parse If Statement and check if there any 'else' is there, if 'yes' then + * parseIt and Break otherwise parse Else if statement and append to a list + */ + + if (error) return null; + + ConditionalBranching ifNode; + if ((ifNode = parseIf()) != null) { + CafeStatement elseBlock = null; + if (token.kind == TokenKind.ELSE) { +// Token elseFT = token; + nextToken(); + if (token.kind == TokenKind.IF) { + elseBlock = parseIfStatement(); + } else if (accept(TokenKind.LCURLY)) { + elseBlock = parseBlock(); + accept(TokenKind.RCURLY); + } + if (error) return null; + ifNode.otherwise(elseBlock); + } + return ifNode; + } + return null; + } + + /* Parse Loops */ + List parseForInit() { + /* + * + * + */ + if (error) return null; + List init = null; + ExpressionStatement iden, val; + Context ctx = Context.context; + if (token.kind == TokenKind.SEMICOLON) + return init; + init = new LinkedList<>(); + while (token.kind == TokenKind.VAR || token.kind == TokenKind.IDENTIFIER) { + if (error) + return null; + if (token.kind == TokenKind.VAR) { + accept(TokenKind.VAR); + iden = parseIdentifier(); + SymbolReference sym = ctx.createSymbolReference(iden.getName(), Node.Tag.VARDECL); + accept(TokenKind.EQU); + val = parseValue(); + DeclarativeAssignmentStatement stmt = DeclarativeAssignmentStatement.create(sym, val); + if (token.kind == TokenKind.COMMA) + nextToken(); + init.add(stmt); + } else { + // this else is not needed but keeping just for reference.. + iden = parseIdentifier(); + SymbolReference sym = ctx.createSymbolReference(iden.getName(), Node.Tag.VARDECL); + accept(TokenKind.EQU); + val = parseValue(); + DeclarativeAssignmentStatement stmt = DeclarativeAssignmentStatement.create(sym, val); + if (token.kind == TokenKind.COMMA) + nextToken(); + init.add(stmt); + } + } + if (error) return null; + if (init.isEmpty()) return null; + return init; + } + + ExpressionStatement parseForCondition() { + /* + * parseLogOrEcpression() + */ + if (error) return null; + ExpressionStatement cond = null; + if (token.kind == TokenKind.SEMICOLON) + return cond; + cond = parseLogicalOrExpression(); + if (error) return null; + return cond; + } + + List> parseForIncrement() { + /* + * + * parseAssignmentStatement() + */ + if (error) return null; + ExpressionStatement iden, val, exp2; + List> incrNodes = null; + if (token.kind == TokenKind.RPAREN) { + return incrNodes; + } + + incrNodes = new ArrayList<>(); + while (token.kind == TokenKind.IDENTIFIER) { + if (error) + return null; + iden = parseIdentifier(); + Context ctx= Context.context; + ctx.enterProperty(); + while (token.kind == TokenKind.DOT) { + if (error) + return null; + accept(TokenKind.DOT); + exp2 = parseIdentifier(); + iden = ObjectAccessStatement.create(iden, exp2); + } + ctx.leaveProperty(); + accept(TokenKind.EQU); + val = parseValue(); + incrNodes.add(AssignmentStatement.create(iden, val)); + if (token.kind == TokenKind.COMMA) + nextToken(); + } + if (error) return null; + return incrNodes; + } + + CafeStatement parseForStatement() { + /* + * accept(FOR) accept(LPAREN) if (SEMI ) parseForCondition() accept(SEMI) + * parseForIncr() else parseForInit() accept(SEMI) parseForCondition() + * accept(SEMI) parseForIncr() + */ + if (error) return null; + Context context = Context.context; + ForLoopStatement forLoop = ForLoopStatement.loop(); + context.forLoopStack.push(forLoop); + List init; + ExpressionStatement cond; + List> incrNode; + Block block; + accept(TokenKind.FOR); + accept(TokenKind.LPAREN); + init = parseForInit(); + accept(TokenKind.SEMICOLON); + cond = parseForCondition(); + accept(TokenKind.SEMICOLON); + incrNode = parseForIncrement(); + accept(TokenKind.RPAREN); + accept(TokenKind.LCURLY); + block = parseLoopBlock(); + accept(TokenKind.RCURLY); + if (error) return null; + forLoop.condition(cond) + .init(init) + .postStatement(incrNode) + .block(block); + context.forLoopStack.pop(); + return forLoop; + } + +// CafeStatement parseLoopStatement() { +// /* +// * accept(LOOP) parseLoopIdentifier() accept(IN) parseLoopValue() +// * parseLoopBlock() parseCollectionComprehension() +// * +// */ +// if (error) return null; +// ExpressionStatement iden1 = null, iden2 = null; +// ExpressionStatement exp = null; +// Block block=null; +// +// accept(TokenKind.LOOP); +// iden1 = parseIdentifier(); +// if (token.kind == TokenKind.COMMA) { +// nextToken(); +// iden2 = parseIdentifier(); +// } +// accept(TokenKind.IN); +// try { +// exp = parseAtomExpression(); +// } catch (ParseException ignored) { +// } +// +// if (exp == null) { +// if (token.kind == TokenKind.LCURLY) +// exp = parseCollection(); +// else +// exp = parseObjectCreation(); +// +// } +// accept(TokenKind.LCURLY); +// block = parseLoopBlock(); +// accept(TokenKind.RCURLY); +// if (error) return null; +// TODO: Implementation of LoopStmt IR node is yet to be done. +// return new LoopStmtNode(iden1, iden2, exp, block); +// return null; +// } + + CafeStatement parseFlowStatement() { + /* + * if(CONTINUE) return ContinueNode if(BREAK) return BreakNode + */ + if (error) return null; + Token tk = token; + Context context = Context.context; + if (breakAllowed) + if (token.kind == TokenKind.CONTINUE) { + accept(TokenKind.CONTINUE); + accept(TokenKind.SEMICOLON); + ContinueStmtNode continueStmtNode = new ContinueStmtNode(); + continueStmtNode.setFirstToken(tk); + return BreakContinueStatement.newContinue() + .setEnclosingLoop(context.forLoopStack.peek()); + } else { + accept(TokenKind.BREAK); + accept(TokenKind.SEMICOLON); + return BreakContinueStatement.newBreak() + .setEnclosingLoop(context.forLoopStack.peek()); + } + else { + error = true; + accept(TokenKind.IDENTIFIER); + } + return null; + } + /* Parse Loop Done */ + + /* Parse Collection */ + ExpressionStatement parseList() { + /* + * List of Values + * + * accept(LBRACKET) List.add(parseValue()) if(COMMA or DOTDOT) + * List.add(parseValue()) else if(LOOP_KEYWORD) + * List.add(parseForComprehension()) + * + * return List + */ + if (error) return null; + ListCollection listNode = ListCollection.list(); + ExpressionStatement exp1; + exp1 = parseValue(); +// if (token.kind == TokenKind.RANGE) { + // TODO: to implement IR node implementation for RANGE + // accept(TokenKind.RANGE); + // exp2 = parseValue(); + // accept(TokenKind.RSQU); + // return new RangeNode(exp1, exp2, RangeNode.Type.LIST); +// } + listNode.add(exp1); + while (token.kind != TokenKind.RSQU) { + if (error) + return null; + accept(TokenKind.COMMA); + if (token.kind == TokenKind.RSQU) accept(TokenKind.IDENTIFIER); + listNode.add(parseValue()); + } + accept(TokenKind.RSQU); + if (error) return null; + return listNode; + } + + ExpressionStatement parseListCollection() { + /* + * List of Collection + * + * if (RBRACKET){ return ListNode() } + * + * else { return parseList(); } + */ + if (error) return null; + accept(TokenKind.LSQU); + if (token.kind == TokenKind.RSQU) { + accept(TokenKind.RSQU); + if (error) return null; + return ListCollection.list(); + } else if (token.kind == TokenKind.LOOP) { + if (error) return null; + // TODO: implement IR node for Comprehension node + // return parseComprehension("list"); // Accept Identifier Before + return null; + } else { + if (error) return null; + return parseList(); + } + } + + ExpressionStatement parseMapCollection() { + /* + * List of MapCollection List of Comp + * + * case: LBRACKET mapCollection.add(parseMap()) + * + * if (COMMA) : mapCollection.add(parseMap()) if (LOOP ) + * Comp.add(parseForComprehension()) + * + */ + // TODO: to implement Map IR node +// if (error) return null; +// Map pairs = new LinkedHashMap<>(); +// nextToken(); +// accept(TokenKind.LSQU); +// debug.add("Map Collection : " + token.kind); +// while (token.kind != TokenKind.RSQU) { +// if (error) +// return null; +// ExprNode exp2 = new MapCollNode(), exp1 = new MapCollNode(); +// if (token.kind == TokenKind.COMMA) +// nextToken(); +// accept(TokenKind.LSQU); +// if (token.kind == TokenKind.RSQU) { +// pairs.put(exp1, exp2); +// accept(TokenKind.RSQU); +// accept(TokenKind.COMMA); +// continue; +// } else if (token.kind == TokenKind.LOOP) { +// return parseComprehension("map"); // Accept Identifier Before +// } else { +// exp1 = parseValue(); +// accept(TokenKind.COMMA); +// exp2 = parseValue(); +// accept(TokenKind.RSQU); +// } +// +// pairs.put(exp1, exp2); +// } +// accept(TokenKind.RSQU); +// if (error) return null; +// return new MapCollNode(pairs); + return null; + } + +// ExpressionStatement parseComprehension(String type) { +// if (error) return null; +// IdenNode iden1, iden2 = null; +// ExprNode exp = null; +// BlockNode block = null; +// ExprNode ifCond; +// +// CompTypeNode mapComp = type == "map" ? new MapCompNode() +// : type == "list" ? new ListCompNode() +// : type == "set" ? new SetCompNode() : type == "link" ? new LinkCompNode() : null; +// +// while (token.kind != TokenKind.RSQU) { +// if (error) +// return null; +// switch (token.kind) { +// case LOOP: +// accept(TokenKind.LOOP); +// iden1 = parseIdentifier(); +// if (token.kind == TokenKind.COMMA) { +// nextToken(); +// iden2 = parseIdentifier(); +// } +// accept(TokenKind.IN); +// exp = parseCollection(); +// if (exp == null) { +// if (token.kind == TokenKind.LCURLY) +// exp = parseObjectCreation(); +// else +// try { +// exp = parseAtomExpression(); +// } catch (ParseException e) { +// } +// } +// mapComp.addExpr(new CompLoopNode(iden1, iden2, exp)); +// break; +// case IF: +// accept(TokenKind.IF); +// accept(TokenKind.LPAREN); +// ifCond = parseLogicalOrExpression(); +// accept(TokenKind.RPAREN); +// debug.add("Comprehension: " + token.kind); +// mapComp.addExpr(new CompIfNode(ifCond)); +// break; +// default: +// error = true; +// accept(TokenKind.IDENTIFIER); +// } +// } +// accept(TokenKind.RSQU); +// if (error) return null; +// return mapComp; +// return null; +// } + + ExpressionStatement parseSetCollection() { + /* + * List of Collection + * + * if (RBRACKET){ return SetNode() } + * + * else { return parseSet(); } + * + * + */ + // TODO: to implement SET IR node +// if (error) return null; +// nextToken(); +// accept(TokenKind.LSQU); +// if (token.kind == TokenKind.RSQU) { +// accept(TokenKind.RSQU); +// if (error) return null; +// return new SetCollNode(); +// } else if (token.kind == TokenKind.LOOP) { +// if (error) return null; +// return parseComprehension("set"); // Accept Identifier Before +// } else { +// if (error) return null; +// return parseSet(); +// } + return null; + } + + ExpressionStatement parseLinkCollection() { + /* + * List of Collection + * + * if (RBRACKET){ return ListNode() } + * + * else { return parseList(); } + * + * + */ + // TODO: to implement LINK IR node +// if (error) return null; +// nextToken(); +// accept(TokenKind.LSQU); +// if (token.kind == TokenKind.RSQU) { +// accept(TokenKind.RSQU); +// if (error) return null; +// return new LinkCollNode(); +// } else if (token.kind == TokenKind.LOOP) { +// if (error) return null; +// return parseComprehension("link"); // Accept Identifier Before +// } else { +// if (error) return null; +// return parseLink(); +// } + + return null; + } + + ExpressionStatement parseCollection() { + /* + * List of Collection + * + * read TokenType: case LBRACKET: parseListCollection() case LINK: case SET: + * parseCollection() case MAP: parseMapCollection() + * + * return List + */ + if (error) return null; + ExpressionStatement collExpr = null; + + switch (token.kind) { + case LSQU: + collExpr = parseListCollection(); + break; + case LINK: + collExpr = parseLinkCollection(); + break; + case SET: + collExpr = parseSetCollection(); + break; + case MAP: + collExpr = parseMapCollection(); + break; + } + if (error) return null; + return collExpr; + + } + + /* Parse Collection Done */ + + /* Parse Values */ + ExpressionStatement parseObjectCreation() { + /* + * List of ObjectNode + * + * List.add(parseObject()) + * + * if Comma { List.add(parseObject()) } + * + */ + + if (error) return null; + Map> object = new LinkedHashMap<>(); + ExpressionStatement idenNode; + ExpressionStatement exprNode; + + accept(TokenKind.LCURLY); + while (token.kind != TokenKind.RCURLY) { + if (error) + return null; + idenNode = parseIdentifier(); + accept(TokenKind.COLON); + exprNode = parseValue(); + object.put(idenNode.getName(), exprNode); + debug.add("Obj Creation Token : " + token.kind); + if (TokenKind.RCURLY != token.kind) + accept(TokenKind.COMMA); + } + debug.add("Object Creation: " + object); + accept(TokenKind.RCURLY); + if (error) return null; + return ObjectCreationStatement.of(object); + } + + AnonymousFunction parseAnnFunction() { + /* + * accept(FUNC) isAnnFunmc = true parseFunction() + * + */ + if (error) return null; + Context context = Context.context; + String funcName = "#_ANN_Hello"; + accept(TokenKind.FUNC); + accept(TokenKind.LPAREN); + context.enterFunc(funcName); + funcName = context.getNextAnnFuncName(); + List params = parseParameter(); + accept(TokenKind.RPAREN); + accept(TokenKind.LCURLY); + debug.add("Ann Func Node: " + token.kind); + Block block = parseBlock(); + accept(TokenKind.RCURLY); + + if (!block.hasReturn()) + block.add(ReturnStatement.of(null)); + CafeFunction function = CafeFunction.function(funcName) + .block(block) + .withParameters(params); + if (context.isExport) + function = function.asExport(); + + context.addFunction(function); + + ExpressionStatement expression; + if (context.currentScope() == IRParser.Context.Scope.CLOSURE) { + expression = function.asClosure(); + } else { + expression = FunctionWrapper.wrap(function); + } + context.leaveFunc(); + TargetFuncWrapper targetFuncWrapper = (TargetFuncWrapper) expression; + AnonymousFunction anonymousFunction = AnonymousFunction.func(targetFuncWrapper); + if (error) return null; + return anonymousFunction; + } + + ExpressionStatement parseValue() { + /* + * ValueNode + * + * checks Grammar + * + * Case Object: parseObjectCreation() Case Collection: parseCollection() Case + * AnnFunc: parseAnnFunction() case Operator: parseBitOrOperator() + * + * return ValueNode + */ + if (error) return null; + ExpressionStatement valExpr ; + debug.add("Parse Value: " + token.kind); + switch (token.kind) { + case LCURLY: + valExpr = parseObjectCreation(); + break; + case LSQU: + case LINK: + case SET: + case MAP: + valExpr = parseCollection(); + break; + + case FUNC: + valExpr = parseAnnFunction(); + break; + + default: + valExpr = parseBitOrExpression(); + break; + + } + if (error) return null; + return valExpr; + } + + /* Parse Values DOne */ + + List parseVariable() { + /* + * List Variables checks grammar for variable Declaration + * + * + * calls parseVariableDeclaration + * + * return List + */ + if (error) return null; + List varDeclNodes = new ArrayList<>(); + accept(TokenKind.VAR); + while (token.kind != TokenKind.SEMICOLON) { + if (error) + return null; + ExpressionStatement iden = parseIdentifier(); + ExpressionStatement exp = null; + Context ctx = Context.context; + if (error) + return null; + if (token.kind == TokenKind.EQU) { + nextToken(); + exp = parseValue(); + } + if (token.kind != TokenKind.SEMICOLON) { + accept(TokenKind.COMMA); + } + debug.add("Var Decl: " + exp); + SymbolReference sym = ctx.createSymbolReference(iden.getName(), Node.Tag.VARDECL); + DeclarativeAssignmentStatement stmt = DeclarativeAssignmentStatement.create(sym, exp); + varDeclNodes.add(stmt); + } + accept(TokenKind.SEMICOLON); + if (error) return null; + return varDeclNodes; + } + + List parseConstVariable() { + /* + * List Variables checks grammar for variable Declaration + * + * + * calls parseVariableDeclaration + * + * return List + */ + if (error) return null; + List constDeclNodes = new ArrayList<>(); + accept(TokenKind.CONST); + Context ctx = Context.context; + while (token.kind != TokenKind.SEMICOLON) { + if (error) + return null; + ExpressionStatement iden = parseIdentifier(); + accept(TokenKind.EQU); + ExpressionStatement exp = parseValue(); + if (token.kind != TokenKind.SEMICOLON) + accept(TokenKind.COMMA); + SymbolReference sym = ctx.createSymbolReference(iden.getName(), Tag.CONSTDECL); + DeclarativeAssignmentStatement stmt = DeclarativeAssignmentStatement.create(sym, exp); + constDeclNodes.add(stmt); + } + accept(TokenKind.SEMICOLON); + if (error) return null; + return constDeclNodes; + } + + List parseParameter() { + /* + * List of Arguments + * + * responsibility: Check Grammar and parseIdentifier + * + * calls: arguments.add = parseIdentifier() arguments.add = varArgs() + * + * return List + */ + if (error) return null; + List idenNodes = new ArrayList<>(); + + while (token.kind != TokenKind.RPAREN) { + if (error) + return null; + debug.add("ARG List: " + token.kind); + debug.add("ARG List: " + token.value()); + + if (token.kind == TokenKind.VARARGS) { + accept(TokenKind.VARARGS); + idenNodes.add(parseIdentifier().getName()); + break; + } + idenNodes.add(parseIdentifier().getName()); + if (TokenKind.RPAREN != token.kind) + accept(TokenKind.COMMA); + } + + if (error) return null; + return idenNodes; + } + + DeclarativeAssignmentStatement parseFunctionDeclaration() { + /* + * List of Parameter BlockNode + * + * calls: name = isAnnFunc ? null : parseIdentifier() parameter = + * parseParameter() BlockNode= parseBlockStatement() + * + * FunctionNode(name, parameter, BlockNode); returns FunctionNode + */ + if (error) return null; + Context context = Context.context; + accept(TokenKind.FUNC); +// Token tk = token; + ExpressionStatement funcName = parseIdentifier(); + context.enterFunc(funcName.getName()); + accept(TokenKind.LPAREN); + List arg = parseParameter(); + accept(TokenKind.RPAREN); + accept(TokenKind.LCURLY); + Block block = parseBlock(); + accept(TokenKind.RCURLY); + if (!block.hasReturn()) + block.add(ReturnStatement.of(null)); + CafeFunction function = CafeFunction.function(funcName.getName()) + .block(block) + .withParameters(arg); + if (context.isExport) + function = function.asExport(); + + context.addFunction(function); + + ExpressionStatement expression; + if (context.currentScope() == IRParser.Context.Scope.CLOSURE) { + expression = function.asClosure(); + } else { + expression = FunctionWrapper.wrap(function); + } + context.leaveFunc(); + SymbolReference ref = context.createSymbolReference(funcName.getName(), Node.Tag.VARDECL); + DeclarativeAssignmentStatement statement = DeclarativeAssignmentStatement.create(ref, expression); + if (error) return null; + + return statement; + } + + ReturnStatement parseReturnStatement() { + if (error) return null; + accept(TokenKind.RET); + ExpressionStatement exp = parseValue(); + debug.add("Return : " + exp); + accept(TokenKind.SEMICOLON); + if (error) return null; + return ReturnStatement.of(exp); + } + + Block parseLoopBlock() { + /* + * parseBlockStatement() parseFlowStatement() + */ + if (error) return null; +// List> blockStats = new ArrayList<>(); +// +// Context context = Context.context; +// Block block = context.enterScope(); +// while (token.kind != TokenKind.RCURLY) { +// if (error) +// return null; +// switch (token.kind) { +// case CONTINUE: +// case BREAK: +// blockStats.add(parseFlowStatement()); +// break; +// default: + Block block = parseBlock(); +// List> stm = parseBlock(); +// if (stm == null) return null; +// blockStats.addAll(stm); +// for (CafeStatement stmt: blockStats){ +// block.add(stmt); +// } +// } +// } + if (error) return null; + return block; + } + List> parseStatement() { + List> block = new ArrayList<>(); + switch (token.kind) { + case VAR: + List stm = parseVariable(); + if (stm == null) return null; + block.addAll(stm); + break; + case CONST: + List stm1 = parseConstVariable(); + if (stm1 == null) return null; + block.addAll(stm1); + break; + case FUNC: + DeclarativeAssignmentStatement decl = parseFunctionDeclaration(); + if (decl == null) return null; + block.add(decl); + break; + case IF: + CafeStatement stm2 = parseIfStatement(); + if (stm2 == null) return null; + block.add(stm2); + break; + case FOR: + boolean innerLoop = breakAllowed; + breakAllowed = true; + CafeStatement stm3 = parseForStatement(); + if (stm3 == null) return null; + block.add(stm3); + breakAllowed = innerLoop; + break; + case LOOP: +// CafeStatement stm4 = parseLoopStatement(); +// if (stm4 == null) return null; +// block.add(stm4); + break; + case RET: + CafeStatement stm5 = parseReturnStatement(); + if (stm5 == null) return null; + block.add(stm5); + break; + case IDENTIFIER: + case THIS: + case NULL: + CafeStatement stm6 = parseExprStmt(); + if (stm6 == null) return null; + block.add(stm6); + accept(TokenKind.SEMICOLON); + break; + case BREAK: + case CONTINUE: + CafeStatement stm7 = parseFlowStatement(); + block.add(stm7); + debug.add("Break Continue Block Stmt: " + token.kind); + break; + default: + logError(TokenKind.IDENTIFIER); + } + if(error) return null; + return block; + } + Block parseBlock() { + /* + * List of block Statements calls parseBlockStatement + */ + if (error) return null; + + Context context = Context.context; + Block block = context.enterScope(); + List> blockStmt = new ArrayList<>(); + debug.add("Token kind " + token.kind); + while(token.kind != TokenKind.RCURLY) { + if (error) return null; + List> stm = parseStatement(); + if (stm == null) return null; + blockStmt.addAll(stm); + } + for(CafeStatement stmt: blockStmt){ + block.add(stmt); + } + + context.leaveScope(); + if (error) return null; + debug.add("Block Stmt: " + block); + return block; + } + + List parseExportStatement() { + List exportStmtNode = new ArrayList<>(); + + Context context = Context.context; + context.isExport = true; + List decl = new ArrayList<>(); + + accept(TokenKind.EXPORT); + switch (token.kind) { + case IDENTIFIER: + ExpressionStatement id = parseIdentifier(); + if (id == null) return null; + exportStmtNode.add(CafeExport.export(id.getName())); + while (token.kind == TokenKind.COMMA) { + accept(TokenKind.COMMA); + id = parseIdentifier(); + if (id == null) return null; + exportStmtNode.add(CafeExport.export(id.getName())); + } + accept(TokenKind.SEMICOLON); + break; + + case VAR: +// List stm = parseVariable(); + decl = parseVariable(); + if (decl == null) return null; + for (DeclarativeAssignmentStatement var : decl) { + exportStmtNode.add(CafeExport.export(var.getSymbolReference().getName())); + } + break; + case CONST: + decl = parseConstVariable(); + if (decl == null) return null; + for (DeclarativeAssignmentStatement var : decl) { + exportStmtNode.add(CafeExport.export(var.getSymbolReference().getName())); + } + break; + case FUNC: + DeclarativeAssignmentStatement funcDecl = parseFunctionDeclaration(); + if (funcDecl == null) return null; + exportStmtNode.add(CafeExport.export(funcDecl.getName())); + decl.add(funcDecl); + break; + default: + error = true; + } + + context.isExport = false; + for(CafeExport expo : exportStmtNode){ + context.module.addExport(expo); + } + if (error) return null; + return decl; + } + + // return Import Statement Node + CafeImport parseImportStatement() { + /* List of Imports */ + + // accept('@'); + // boolean valid = checkFilePathRegex(token.value()); + // if(valid) return ImportStatement(token.value()) + // else Throw Error +// ImportStmtNode importStmtNode = null; + Map blocks = new HashMap<>(); + ExpressionStatement id1, id2 = null; + Context context = Context.context; + + accept(TokenKind.IMPORT); + if(token.kind == TokenKind.IDENTIFIER){ + id1 = parseIdentifier(); + if (token.kind == TokenKind.AS) { + accept(token.kind); + id2 = parseIdentifier(); + } + blocks.put(id1.getName(), id2 != null ? id2.getName() : null); + while (token.kind == TokenKind.COMMA) { + accept(TokenKind.COMMA); + id1 = parseIdentifier(); + id2 = null; + if (token.kind == TokenKind.AS) { + accept(token.kind); + id2 = parseIdentifier(); + } + blocks.put(id1.getName(), id2 != null ? id2.getName() : null); + } + } else { + if(accept(TokenKind.MUL)) { + accept(TokenKind.AS); + id2 = parseIdentifier(); + blocks.put("*", id2.getName()); + } + } + + accept(TokenKind.FROM); +// File file = new File(token.value()+".class"); +// if(!file.exists()){ +// +// logError(INVALID_IMPORT_FILE, token.value()); +// error = true; +// } else { + + CafeImport cafeImport = CafeImport.of(token.value()); +// importStmtNode = new ImportStmtNode(blocks, token.value()); + nextToken(); + accept(TokenKind.SEMICOLON); + for (Map.Entry entry : blocks.entrySet()) { + cafeImport.add(entry.getKey(), entry.getValue()); + } + context.module.addImport(cafeImport); + return cafeImport; + } + + // return Statement Node + + // return List Of Statements + CafeModule parseStatements() { + /* + * List of Statement stats + * + * calls parseStatement() + */ + + // nextToken(); + // while(token.kind != END){ + // StatementNode stat= parseStatement(); + // stats.add(stat); + // nextToken(); + // } + // return ProgramNode(stats); + if (error) return null; + + nextToken(); + debug.add("Stmt Node Token: " + token.kind); + List> tree = new ArrayList<>(); + while (token.kind != TokenKind.END) { + if (error) + return null; + switch (token.kind) { + case IMPORT: + CafeImport importStmtNode = parseImportStatement(); + if (importStmtNode == null) return null; + tree.add(importStmtNode); + break; + case EXPORT: + List exports = parseExportStatement(); + if(exports == null) return null; + tree.addAll(exports); + break; + default: + List> stmt = parseStatement(); + if (stmt == null) return null; + tree.addAll(stmt); + break; + } + } + if (error) return null; + debug.add("Block Statements " + tree); + for( CafeStatement stm: tree){ + Context.context.module.add(stm); + } + return Context.context.module; + } +} diff --git a/src/main/java/compiler/parser/Parser.java b/src/main/java/compiler/parser/Parser.java index 9eb5bec..e6ff087 100644 --- a/src/main/java/compiler/parser/Parser.java +++ b/src/main/java/compiler/parser/Parser.java @@ -29,10 +29,8 @@ package compiler.parser; -import compiler.ast.Node; - public abstract class Parser { abstract Parser instance(ParserFactory factory, Lexer lexer); - public abstract Node parse(); + public abstract T parse(String moduleName); } \ No newline at end of file diff --git a/src/main/java/compiler/parser/ParserType.java b/src/main/java/compiler/parser/ParserType.java index 98af939..8d72259 100644 --- a/src/main/java/compiler/parser/ParserType.java +++ b/src/main/java/compiler/parser/ParserType.java @@ -35,8 +35,8 @@ * @author Dhyey */ public enum ParserType { - MAINPARSER("MainParser"); - + ASTParser("ASTParser"), + IRParser("IRParser"); String parserClassName; ParserType(String className) { diff --git a/src/test/java/compiler/parser/MainParserTest.java b/src/test/java/compiler/parser/ASTParserTest.java similarity index 80% rename from src/test/java/compiler/parser/MainParserTest.java rename to src/test/java/compiler/parser/ASTParserTest.java index d0ba0d6..0dd4ea9 100644 --- a/src/test/java/compiler/parser/MainParserTest.java +++ b/src/test/java/compiler/parser/ASTParserTest.java @@ -29,7 +29,7 @@ package compiler.parser; -import compiler.ast.Node; +import compiler.ir.CafeModule; import compiler.main.SourceFileManager; import compiler.util.Context; import org.testng.annotations.BeforeMethod; @@ -43,7 +43,7 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -public class MainParserTest { +public class ASTParserTest { public static final String SRC = "src/test/resources/parse-test/"; public static final String ERR = "src/test/resources/parse-test/error_test"; @@ -70,16 +70,20 @@ public void init() { @Test(dataProvider = "cafe-files") public void test_no_error(File file) { fm.setSourceFile(file); - Parser parser = factory.newParser(ParserType.MAINPARSER, fm.asCharList()); - Node n = parser.parse(); - assertNotNull(n); + Parser parser = factory.newParser(ParserType.IRParser, fm.asCharList()); + CafeModule module = parser.parse(file.getName()); + System.out.println("Success "+module); +// Node n = parser.parse(); + assertNotNull(module); } @Test(dataProvider = "cafe-error-files") public void test_error(File file) { fm.setSourceFile(file); - Parser parser = factory.newParser(ParserType.MAINPARSER, fm.asCharList()); - Node n = parser.parse(); - assertNull(n); + Parser parser = factory.newParser(ParserType.IRParser, fm.asCharList()); + CafeModule module = parser.parse(file.getName()); + System.out.println("Success "+module); +// Node n = parser.parse(); + assertNull(module); } } diff --git a/src/test/resources/ann-func-test/anonymous_func_export.class b/src/test/resources/ann-func-test/anonymous_func_export.class new file mode 100644 index 0000000..d7a6aed Binary files /dev/null and b/src/test/resources/ann-func-test/anonymous_func_export.class differ diff --git a/src/test/resources/ann-func-test/as-closure/ann_func_export.class b/src/test/resources/ann-func-test/as-closure/ann_func_export.class new file mode 100644 index 0000000..7cbf3f5 Binary files /dev/null and b/src/test/resources/ann-func-test/as-closure/ann_func_export.class differ