diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 581c216..4e7a66a 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 687f0c0..ea683db 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/generate.py b/generate.py
new file mode 100644
index 0000000..4d5ab82
--- /dev/null
+++ b/generate.py
@@ -0,0 +1,53 @@
+from collections import defaultdict
+
+data = open('./grammar.txt').read().split()
+
+productions = defaultdict(lambda: [])
+
+
+def recurse(prod):
+ prods = []
+ if prod not in productions.keys():
+ prods.append(prod)
+ else:
+ for p in productions[prod]:
+ if len(p):
+ prods += recurse(p[0])
+
+ return prods
+
+
+while len(data):
+ name = data.pop(0)
+ data.pop(0) # ->
+
+ symbols = []
+ while True:
+ symbol = data.pop(0)
+ if symbol == '.':
+ productions[name].append(symbols)
+ break
+ if symbol == '|':
+ productions[name].append(symbols)
+ symbols = []
+ continue
+ symbols.append(symbol)
+
+for prod, defs in productions.items():
+ func = f"""private void {prod}() {{
+ Token token = lexAn.peekToken();
+ switch(token.symbol()) {{
+"""
+ for d in defs:
+ for r in recurse(d[0]):
+ func += f" case {r}:\n"
+
+ func += f' System.out.println("{prod} -> {defs}");'
+
+ for d2 in d:
+ if d2.isupper():
+ func += f"check({d2});"
+
+ func += """ }
+}"""
+ print(func)
diff --git a/grammar.txt b/grammar.txt
index 920531b..b9e804d 100644
--- a/grammar.txt
+++ b/grammar.txt
@@ -1,48 +1,54 @@
program -> definition restdefs .
restdefs -> definition restdefs | .
-definition -> fun IDENTIFIER LPAREN parameters RPAREN funcassign .
+definition -> FUN IDENTIFIER LPAREN parameters RPAREN funcassign .
funcassign -> ASSIGN statements | .
-definition -> var IDENTIFIER ASSING initializers .
+definition -> VAR IDENTIFIER ASSIGN initializers .
parameters -> IDENTIFIER restparams | .
-restparams -> COMMA parameters | .
+restparams -> COMMA IDENTIFIER restparams | .
statements -> statement reststmts .
-reststmts -> COMMA statements | .
+reststmts -> COMMA statement reststmts | .
statement -> expression exprassign .
exprassign -> ASSIGN expression | .
-statement -> if expression then statements elsestmt end .
-elsestmt -> else statements | .
+statement -> IF expression THEN statements elsestmt END .
+elsestmt -> ELSE statements | .
-statement -> while expression do statements end .
+statement -> WHILE expression DO statements END .
-statement -> let definition reststmtdefs in statements end .
+statement -> LET definition reststmtdefs IN statements END .
reststmtdefs -> definition reststmtdefs | .
expression -> conjexpr restdisj .
-restdisj -> OR expression | .
+restdisj -> OR conjexpr restdisj | .
conjexpr -> cmpexpr restconj .
-restconj -> AND conjexpr | .
+restconj -> AND cmpexpr restconj | .
cmpexpr -> addexpr restcmp .
-restcmp -> cmpop cmpexpr | .
-cmpop -> EQ | NEQ | LTH | GTH | LEQ | GEQ .
+restcmp -> EQU addexpr
+ | NEQ addexpr
+ | LTH addexpr
+ | GTH addexpr
+ | LEQ addexpr
+ | GEQ addexpr
+ | .
addexpr -> multexpr restadd .
-restadd -> addop addexpr | .
-addop -> ADD | SUB .
+restadd -> ADD multexpr restadd
+ | SUB multexpr restadd | .
multexpr -> prefixexpr restmult .
-restmult -> multop multexpr | .
-multop -> MUL | DIV | MOD .
+restmult -> MUL prefixexpr restmult
+ | DIV prefixexpr restmult
+ | MOD prefixexpr restmult
+ | .
-prefixexpr -> prefixop postfixexpr .
-prefixop -> NOT prefixop | ADD prefixop | SUB prefixop | PTR prefixop | .
+prefixexpr -> NOT prefixexpr | ADD prefixexpr | SUB prefixexpr | PTR prefixexpr | postfixexpr .
postfixexpr -> primary postfixop .
postfixop -> PTR postfixop | .
@@ -51,12 +57,12 @@ primary -> const | LPAREN expression RPAREN | IDENTIFIER exprargs .
exprargs -> LPAREN arguments RPAREN | .
arguments -> expression restargs | .
-restargs -> COMMA restargs | .
+restargs -> COMMA expression restargs | .
initializers -> initializer restinits | .
-restinits -> COMMA initializers | .
+restinits -> COMMA initializer restinits | .
-initializer -> INTCONST intconstmul | CHARCONST | STRINGCONST .
-intconstmul -> MUL const | .
+initializer -> INTCONST intconstmult | CHARCONST | STRINGCONST .
+intconstmult -> MUL const | .
const -> INTCONST | CHARCONST | STRINGCONST .
\ No newline at end of file
diff --git a/pns.iml b/pns.iml
index c90834f..7f55ad5 100644
--- a/pns.iml
+++ b/pns.iml
@@ -1,5 +1,10 @@
+
+
+
+
+
@@ -7,5 +12,6 @@
+
\ No newline at end of file
diff --git a/prg/pass.pins b/prg/pass.pins
new file mode 100644
index 0000000..459fe2c
--- /dev/null
+++ b/prg/pass.pins
@@ -0,0 +1,35 @@
+fun noarg()
+fun onearg(a)
+fun multargs(a, b)
+fun funcassign(a) =
+ a = 1
+
+var a = 1
+var b = 'a'
+var c = "test"
+var e = 'a', "test", 4
+var f = 1 * 3
+var g = 1 * 'a'
+var h = 4 * "aaa"
+
+fun a() =
+ 1, 'a', "a",
+ a, neki(a, 1, 'a', "a"),
+ a^, a^^,
+ +a, -a, !a, ^a, +-!^a,
+ a * b, a / b, a % b, a * b / c % d,
+ a + b, a - b,
+ a == b, a != b, a < b, a > b, a <= b, a >= b,
+ a && b, a && b && c,
+ a || b, a || b || c,
+ (1), (a + b), (a - (!(1) * 2)),
+ a + 1 = b - 1,
+ if a then b end,
+ if a == 3 then b = 1, !c end,
+ if !a then b else a = 3 * a end,
+ if a then b else a, b end,
+ while a <= 10 do a + 1 end,
+ while a <= 10 do a + 1, ^c end,
+ let fun a(b, c) in !b end,
+ let fun a(b, c) var e = 'o' in !b end,
+ let fun a(b, c) in !b, 4 end
diff --git a/prg/test.pins b/prg/test.pins
index 4fbe95f..e69de29 100644
--- a/prg/test.pins
+++ b/prg/test.pins
@@ -1,2 +0,0 @@
-fun test(a, b,,) =
- var c = 0
\ No newline at end of file
diff --git a/src/pins25/common/Token.java b/src/pins25/common/Token.java
index 8735449..d30b890 100644
--- a/src/pins25/common/Token.java
+++ b/src/pins25/common/Token.java
@@ -1,98 +1,205 @@
package pins25.common;
+import java.util.HashMap;
+
/**
* Leksikalni simbol.
- *
+ *
* @param location Lokacija simbola v izvornem programu.
* @param symbol Vrsta simbola.
* @param lexeme Znakovna predstavitev simbola.
*/
public record Token(Report.Location location, Symbol symbol, String lexeme) implements Report.Locatable {
- /**
- * Vrste leksikalnih simbolov.
- */
- public enum Symbol {
- /** Konec datoteke. */
- EOF,
- /** Stevilo. */
- INTCONST,
- /** Znak. */
- CHARCONST,
- /** Niz znakov. */
- STRINGCONST,
- /** Ime. */
- IDENTIFIER,
- /** Kljucna beseda {@code fun}. */
- FUN,
- /** Kljucna beseda {@code var}. */
- VAR,
- /** Kljucna beseda {@code if}. */
- IF,
- /** Kljucna beseda {@code then}. */
- THEN,
- /** Kljucna beseda {@code else}. */
- ELSE,
- /** Kljucna beseda {@code while}. */
- WHILE,
- /** Kljucna beseda {@code do}. */
- DO,
- /** Kljucna beseda {@code let}. */
- LET,
- /** Kljucna beseda {@code in}. */
- IN,
- /** Kljucna beseda {@code end}. */
- END,
- /** Simbol {@code =}. */
- ASSIGN,
- /** Simbol {@code ,}. */
- COMMA,
- /** Simbol {@code &&}. */
- AND,
- /** Simbol {@code ||}. */
- OR,
- /** Simbol {@code !}. */
- NOT,
- /** Simbol {@code ==}. */
- EQU,
- /** Simbol {@code !=}. */
- NEQ,
- /** Simbol {@code >}. */
- GTH,
- /** Simbol {@code <}. */
- LTH,
- /** Simbol {@code >=}. */
- GEQ,
- /** Simbol {@code <=}. */
- LEQ,
- /** Simbol {@code +}. */
- ADD,
- /** Simbol {@code -}. */
- SUB,
- /** Simbol {@code *}. */
- MUL,
- /** Simbol {@code /}. */
- DIV,
- /** Simbol {@code %}. */
- MOD,
- /** Simbol {@code ^}. */
- PTR,
- /** Simbol {@code (}. */
- LPAREN,
- /** Simbol {@code )}. */
- RPAREN,
- }
+ /**
+ * Vrste leksikalnih simbolov.
+ */
+ public enum Symbol {
+ /**
+ * Konec datoteke.
+ */
+ EOF,
+ /**
+ * Stevilo.
+ */
+ INTCONST,
+ /**
+ * Znak.
+ */
+ CHARCONST,
+ /**
+ * Niz znakov.
+ */
+ STRINGCONST,
+ /**
+ * Ime.
+ */
+ IDENTIFIER,
+ /**
+ * Kljucna beseda {@code fun}.
+ */
+ FUN,
+ /**
+ * Kljucna beseda {@code var}.
+ */
+ VAR,
+ /**
+ * Kljucna beseda {@code if}.
+ */
+ IF,
+ /**
+ * Kljucna beseda {@code then}.
+ */
+ THEN,
+ /**
+ * Kljucna beseda {@code else}.
+ */
+ ELSE,
+ /**
+ * Kljucna beseda {@code while}.
+ */
+ WHILE,
+ /**
+ * Kljucna beseda {@code do}.
+ */
+ DO,
+ /**
+ * Kljucna beseda {@code let}.
+ */
+ LET,
+ /**
+ * Kljucna beseda {@code in}.
+ */
+ IN,
+ /**
+ * Kljucna beseda {@code end}.
+ */
+ END,
+ /**
+ * Simbol {@code =}.
+ */
+ ASSIGN,
+ /**
+ * Simbol {@code ,}.
+ */
+ COMMA,
+ /**
+ * Simbol {@code &&}.
+ */
+ AND,
+ /**
+ * Simbol {@code ||}.
+ */
+ OR,
+ /**
+ * Simbol {@code !}.
+ */
+ NOT,
+ /**
+ * Simbol {@code ==}.
+ */
+ EQU,
+ /**
+ * Simbol {@code !=}.
+ */
+ NEQ,
+ /**
+ * Simbol {@code >}.
+ */
+ GTH,
+ /**
+ * Simbol {@code <}.
+ */
+ LTH,
+ /**
+ * Simbol {@code >=}.
+ */
+ GEQ,
+ /**
+ * Simbol {@code <=}.
+ */
+ LEQ,
+ /**
+ * Simbol {@code +}.
+ */
+ ADD,
+ /**
+ * Simbol {@code -}.
+ */
+ SUB,
+ /**
+ * Simbol {@code *}.
+ */
+ MUL,
+ /**
+ * Simbol {@code /}.
+ */
+ DIV,
+ /**
+ * Simbol {@code %}.
+ */
+ MOD,
+ /**
+ * Simbol {@code ^}.
+ */
+ PTR,
+ /**
+ * Simbol {@code (}.
+ */
+ LPAREN,
+ /**
+ * Simbol {@code )}.
+ */
+ RPAREN;
- @Override
- public String toString() {
- String lexeme = switch (symbol) {
- case INTCONST -> "(" + this.lexeme + ")";
- case CHARCONST -> "(" + this.lexeme + ")";
- case STRINGCONST -> "(" + this.lexeme + ")";
- case IDENTIFIER -> "(" + this.lexeme + ")";
- default -> "";
- };
- return location + " " + symbol + lexeme;
- }
+ public String prettyPrint() {
+ return switch (this) {
+ case INTCONST -> "integer constant";
+ case CHARCONST -> "character constant";
+ case STRINGCONST -> "string constant";
+ case IDENTIFIER -> "identifier";
+ case FUN -> "'fun'";
+ case VAR -> "'var'";
+ case IF -> "'if'";
+ case THEN -> "'then'";
+ case ELSE -> "'else'";
+ case WHILE -> "'while'";
+ case DO -> "'do'";
+ case LET -> "'let'";
+ case IN -> "'in'";
+ case END -> "'end'";
+ case ASSIGN -> "'='";
+ case COMMA -> "','";
+ case AND -> "'&&'";
+ case OR -> "'||'";
+ case NOT -> "'!'";
+ case EQU -> "'=='";
+ case NEQ -> "'!='";
+ case GTH -> "'>'";
+ case LTH -> "'<'";
+ case GEQ -> "'>='";
+ case LEQ -> "'<='";
+ case ADD -> "'+'";
+ case SUB -> "'-'";
+ case MUL -> "'*'";
+ case DIV -> "'/'";
+ case MOD -> "'%'";
+ case PTR -> "'^'";
+ case LPAREN -> "'('";
+ case RPAREN -> "')'";
+ default -> this.toString();
+ };
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ String lexeme = switch (symbol) {
+ case INTCONST, IDENTIFIER, CHARCONST, STRINGCONST -> "(" + this.lexeme + ")";
+ default -> "";
+ };
+ return location + " " + symbol + lexeme;
+ }
}
\ No newline at end of file
diff --git a/src/pins25/phase/SynAn.java b/src/pins25/phase/SynAn.java
index 8eca340..6955e36 100644
--- a/src/pins25/phase/SynAn.java
+++ b/src/pins25/phase/SynAn.java
@@ -38,7 +38,7 @@ public class SynAn implements AutoCloseable {
private Token check(Token.Symbol symbol) {
final Token token = lexAn.takeToken();
if (token.symbol() != symbol)
- throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected " + symbol + ".");
+ throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected " + symbol.prettyPrint() + ".");
return token;
}
@@ -54,21 +54,26 @@ public class SynAn implements AutoCloseable {
}
private void parseProgram() {
+ System.out.println("program -> definition restdefs");
parseDefinition();
parseRestDefinitions();
}
private void parseRestDefinitions() {
if (lexAn.peekToken().symbol() != Token.Symbol.EOF) {
+ System.out.println("restdefs -> definition restdefs");
parseDefinition();
parseRestDefinitions();
+ } else {
+ System.out.println("restdefs -> ε");
}
}
private void parseDefinition() {
Token token = lexAn.peekToken();
switch (token.symbol()) {
- case Token.Symbol.FUN:
+ case FUN:
+ System.out.println("definition -> FUN IDENTIFIER LPAREN parameters RPAREN funcassign");
check(Token.Symbol.FUN);
check(Token.Symbol.IDENTIFIER);
check(Token.Symbol.LPAREN);
@@ -77,7 +82,8 @@ public class SynAn implements AutoCloseable {
parseFunctionAssignment();
break;
- case Token.Symbol.VAR:
+ case VAR:
+ System.out.println("definition -> VAR IDENTIFIER ASSIGN initializers");
check(Token.Symbol.VAR);
check(Token.Symbol.IDENTIFIER);
check(Token.Symbol.ASSIGN);
@@ -91,78 +97,80 @@ public class SynAn implements AutoCloseable {
private void parseFunctionAssignment() {
Token token = lexAn.peekToken();
- switch (token.symbol()) {
- case Token.Symbol.FUN:
- case Token.Symbol.VAR:
- case Token.Symbol.IN:
- case Token.Symbol.EOF:
- break;
-
- case Token.Symbol.ASSIGN:
- check(Token.Symbol.ASSIGN);
- parseStatements();
- break;
-
- default:
- throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected ASSIGN.");
+ if (token.symbol() == Token.Symbol.ASSIGN) {
+ System.out.println("funcassign -> ASSIGN statements");
+ check(Token.Symbol.ASSIGN);
+ parseStatements();
+ } else {
+ System.out.println("funcassign -> ε");
}
}
private void parseParameters() {
Token token = lexAn.peekToken();
- switch (token.symbol()) {
- case Token.Symbol.IDENTIFIER:
- check(Token.Symbol.IDENTIFIER);
- parseRestParameters();
- break;
-
- case Token.Symbol.RPAREN:
- break;
-
- default:
- throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected IDENTIFIER or RPAREN.");
+ if (token.symbol() == Token.Symbol.IDENTIFIER) {
+ System.out.println("parameters -> IDENTIFIER restparams");
+ check(Token.Symbol.IDENTIFIER);
+ parseRestParameters();
+ } else {
+ System.out.println("parameters -> ε");
}
}
private void parseRestParameters() {
Token token = lexAn.peekToken();
- switch (token.symbol()) {
- case Token.Symbol.RPAREN:
- break;
-
- case Token.Symbol.COMMA:
- check(Token.Symbol.COMMA);
- check(Token.Symbol.IDENTIFIER);
- parseRestParameters();
- break;
-
- default:
- throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected ')' or ','.");
+ if (token.symbol() == Token.Symbol.COMMA) {
+ System.out.println("restparams -> COMMA IDENTIFIER restparams");
+ check(Token.Symbol.COMMA);
+ check(Token.Symbol.IDENTIFIER);
+ parseRestParameters();
+ } else {
+ System.out.println("restparams -> ε");
}
}
private void parseStatements() {
+ System.out.println("statements -> statement reststmts");
parseStatement();
parseRestStatements();
}
+ private void parseExpressionAssign() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.ASSIGN) {
+ System.out.println("exprassign -> ASSIGN expression");
+ check(Token.Symbol.ASSIGN);
+ parseExpression();
+ } else {
+ System.out.println("exprassign -> ε");
+ }
+ }
+
+ private void parseElseStatement() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.ELSE) {
+ System.out.println("elsestmt -> ELSE statements");
+ check(Token.Symbol.ELSE);
+ parseStatements();
+ } else {
+ System.out.println("elsestmt -> ε");
+ }
+ }
+
+ private void parseRestStatements() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.COMMA) {
+ System.out.println("reststmts -> COMMA statement reststmts");
+ check(Token.Symbol.COMMA);
+ parseStatement();
+ parseRestStatements();
+ } else {
+ System.out.println("reststmts -> ε");
+ }
+ }
+
private void parseStatement() {
Token token = lexAn.peekToken();
switch (token.symbol()) {
- case Token.Symbol.IDENTIFIER:
- case Token.Symbol.LPAREN:
- case Token.Symbol.ADD:
- case Token.Symbol.SUB:
- case Token.Symbol.NOT:
- case Token.Symbol.PTR:
- case Token.Symbol.INTCONST:
- case Token.Symbol.CHARCONST:
- case Token.Symbol.STRINGCONST:
- parseExpression();
- parseExpressionAssign();
- break;
-
- case Token.Symbol.IF:
+ case IF:
+ System.out.println("statement -> if expression then statements elsestmt end");
check(Token.Symbol.IF);
parseExpression();
check(Token.Symbol.THEN);
@@ -171,7 +179,8 @@ public class SynAn implements AutoCloseable {
check(Token.Symbol.END);
break;
- case Token.Symbol.WHILE:
+ case WHILE:
+ System.out.println("statement -> while expression do statements end");
check(Token.Symbol.WHILE);
parseExpression();
check(Token.Symbol.DO);
@@ -179,7 +188,8 @@ public class SynAn implements AutoCloseable {
check(Token.Symbol.END);
break;
- case Token.Symbol.LET:
+ case LET:
+ System.out.println("statement -> let definition reststmtdefs in statements end");
check(Token.Symbol.LET);
parseDefinition();
parseRestStatementDefinitions();
@@ -187,33 +197,318 @@ public class SynAn implements AutoCloseable {
parseStatements();
check(Token.Symbol.END);
break;
- }
- }
- private void parseRestStatements() {
- if (lexAn.peekToken().symbol() == Token.Symbol.COMMA) {
- check(Token.Symbol.COMMA);
- parseStatements();
+ default:
+ System.out.println("statement -> expression exprassign");
+ parseExpression();
+ parseExpressionAssign();
}
}
private void parseRestStatementDefinitions() {
+ switch (lexAn.peekToken().symbol()) {
+ case IN:
+ System.out.println("reststmtdefs -> ε");
+ break;
+ case FUN:
+ case VAR:
+ System.out.println("reststmtdefs -> definition reststmtdefs");
+ parseDefinition();
+ parseRestStatementDefinitions();
+ break;
+ }
}
private void parseInitializers() {
+ switch (lexAn.peekToken().symbol()) {
+ case INTCONST:
+ case CHARCONST:
+ case STRINGCONST:
+ System.out.println("initializers -> initializer restinits");
+ parseInitializer();
+ parseRestInitializers();
+ break;
+ default:
+ System.out.println("initializers -> ε");
+ break;
+ }
}
+ private void parseInitializer() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case INTCONST:
+ System.out.println("initializer -> INTCONST intconstmult");
+ check(Token.Symbol.INTCONST);
+ parseIntegerConstantMultiplier();
+ break;
+
+ case CHARCONST:
+ System.out.println("initializer -> CHARCONST");
+ check(Token.Symbol.CHARCONST);
+ break;
+
+ case STRINGCONST:
+ System.out.println("initializer -> STRINGCONST");
+ check(Token.Symbol.STRINGCONST);
+ break;
+
+ default:
+ throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected integer, character or string constant.");
+ }
+ }
+
+ private void parseRestInitializers() {
+ Token token = lexAn.peekToken();
+ if (token.symbol() == Token.Symbol.COMMA) {
+ System.out.println("restinits -> COMMA initializer restinits");
+ check(Token.Symbol.COMMA);
+ parseInitializer();
+ parseRestInitializers();
+ } else {
+ System.out.println("restinits -> ε");
+ }
+ }
+
+ private void parseIntegerConstantMultiplier() {
+ Token token = lexAn.peekToken();
+ if (token.symbol() == Token.Symbol.MUL) {
+ System.out.println("intconstmult -> MUL const");
+ check(Token.Symbol.MUL);
+ parseConstant();
+ } else {
+ System.out.println("intconstmult -> ε");
+ }
+ }
+
+ private void parseConstant() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case INTCONST:
+ System.out.println("const -> INTCONST");
+ check(Token.Symbol.INTCONST);
+ break;
+
+ case CHARCONST:
+ System.out.println("const -> CHARCONST");
+ check(Token.Symbol.CHARCONST);
+ break;
+
+ case STRINGCONST:
+ System.out.println("const -> STRINGCONST");
+ check(Token.Symbol.STRINGCONST);
+ break;
+
+ default:
+ throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected integer, character or string constant.");
+ }
+ }
+
+
private void parseExpression() {
+ System.out.println("expression -> conjexpr restdisj");
+ parseConjunctionExpression();
+ parseRestDisjunctions();
}
- private void parseExpressionAssign() {
+ private void parseRestDisjunctions() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.OR) {
+ System.out.println("restdisj -> OR conjexpr restdisj");
+ check(Token.Symbol.OR);
+ parseConjunctionExpression();
+ parseRestDisjunctions();
+ }
}
- private void parseElseStatement() {
+ private void parseConjunctionExpression() {
+ System.out.println("conjexpr -> cmpexpr restconj");
+ parseComparisonExpression();
+ parseRestConjunctionExpressions();
}
+ private void parseRestConjunctionExpressions() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.AND) {
+ System.out.println("restconj -> AND cmpexpr restconj");
+ check(Token.Symbol.AND);
+ parseComparisonExpression();
+ parseRestConjunctionExpressions();
+ } else {
+ System.out.println("restconj -> ε");
+ }
+ }
+
+ private void parseComparisonExpression() {
+ System.out.println("cmpexpr -> addexpr restcmp");
+ parseAdditionExpression();
+ parseRestComparisons();
+ }
+
+ private void parseRestComparisons() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case EQU:
+ case NEQ:
+ case LTH:
+ case GTH:
+ case LEQ:
+ case GEQ:
+ System.out.printf("restcmp -> %s addexpr\n", token.symbol());
+ check(token.symbol());
+ parseAdditionExpression();
+ break;
+
+ default:
+ System.out.println("restcmp -> ε");
+ break;
+ }
+ }
+
+ private void parseAdditionExpression() {
+ System.out.println("addexpr -> multexpr restadd");
+ parseMultiplicationExpression();
+ parseRestAdditions();
+ }
+
+ private void parseRestAdditions() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case ADD:
+ case SUB:
+ System.out.printf("restadd -> %s multexpr restadd\n", token.symbol());
+ check(token.symbol());
+ parseMultiplicationExpression();
+ parseRestAdditions();
+ break;
+
+ default:
+ System.out.println("restadd -> ε");
+ break;
+ }
+ }
+
+ private void parseMultiplicationExpression() {
+ System.out.println("multexpr -> prefixexpr restmult");
+ parsePrefixExpression();
+ parseRestMultiplicationExpressions();
+ }
+
+ private void parseRestMultiplicationExpressions() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case MUL:
+ case DIV:
+ case MOD:
+ System.out.printf("restmult -> %s prefixexpr restmult\n", token.symbol());
+ check(token.symbol());
+ parsePrefixExpression();
+ parseRestMultiplicationExpressions();
+ break;
+
+ default:
+ System.out.println("restmult -> ε");
+ break;
+ }
+ }
+
+ private void parsePrefixExpression() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case ADD:
+ case SUB:
+ case NOT:
+ case PTR:
+ System.out.printf("prefixexpr -> %s prefixexpr\n", token.symbol());
+ check(token.symbol());
+ parsePrefixExpression();
+ break;
+
+ default:
+ System.out.println("prefixexpr -> postfixexpr");
+ parsePostfixExpression();
+ break;
+ }
+ }
+
+ private void parsePostfixExpression() {
+ System.out.println("postfixexpr -> primary postfixop");
+ parsePrimary();
+ parsePostfixOperator();
+ }
+
+ private void parsePostfixOperator() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.PTR) {
+ System.out.println("postfixop -> PTR postfixop");
+ check(Token.Symbol.PTR);
+ parsePostfixOperator();
+ } else {
+ System.out.println("postfixop -> ε");
+ }
+ }
+
+ private void parsePrimary() {
+ Token token = lexAn.peekToken();
+ switch (token.symbol()) {
+ case IDENTIFIER:
+ System.out.println("primary -> IDENTIFIER exprargs");
+ check(Token.Symbol.IDENTIFIER);
+ parseExpressionArguments();
+ break;
+
+ case LPAREN:
+ System.out.println("primary -> LPAREN expression RPAREN");
+ check(Token.Symbol.LPAREN);
+ parseExpression();
+ check(Token.Symbol.RPAREN);
+ break;
+
+ case INTCONST:
+ case CHARCONST:
+ case STRINGCONST:
+ System.out.println("primary -> const");
+ parseConstant();
+ break;
+
+ default:
+ throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected identifier, constant or '('.");
+ }
+ }
+
+ private void parseExpressionArguments() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.LPAREN) {
+ System.out.println("exprargs -> LPAREN arguments RPAREN");
+ check(Token.Symbol.LPAREN);
+ parseArguments();
+ check(Token.Symbol.RPAREN);
+ } else {
+ System.out.println("exprargs -> ε");
+ }
+ }
+
+ private void parseArguments() {
+ Token token = lexAn.peekToken();
+ if (token.symbol() == Token.Symbol.RPAREN) {
+ System.out.println("arguments -> ε");
+ } else {
+ System.out.println("arguments -> expression restargs");
+ parseExpression();
+ parseRestArguments();
+ }
+ }
+
+ private void parseRestArguments() {
+ if (lexAn.peekToken().symbol() == Token.Symbol.COMMA) {
+ System.out.println("restargs -> COMMA restargs");
+ check(Token.Symbol.COMMA);
+ parseExpression();
+ parseRestArguments();
+ } else {
+ System.out.println("restargs -> ε");
+ }
+ }
+
+
// --- ZAGON ---
/**