AST
This commit is contained in:
parent
a4773edb76
commit
a8f08725aa
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
out/
|
||||
|
||||
**/.DS_Store
|
||||
**/.DS_Store
|
||||
*.zip
|
1
.idea/misc.xml
generated
1
.idea/misc.xml
generated
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.12" />
|
||||
|
6
pns.iml
6
pns.iml
@ -1,10 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Python" name="Python">
|
||||
<configuration sdkName="Python 3.12" />
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
@ -12,6 +7,5 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Python 3.12 interpreter library" level="application" />
|
||||
</component>
|
||||
</module>
|
@ -1,2 +0,0 @@
|
||||
fun a() =
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2>3) || (1<=2) && 1 >= c))^^^^^
|
@ -1,4 +0,0 @@
|
||||
fun a() =
|
||||
while 1 then
|
||||
neki
|
||||
end
|
@ -1,24 +0,0 @@
|
||||
var _kfoai = 8 * "neki"
|
||||
var fkaio92j0a = 1 * 'a'
|
||||
|
||||
fun a (c,dvv,d,f,d)
|
||||
fun a() =
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
else
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
||||
while !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ do
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
@ -1 +0,0 @@
|
||||
fun a() =
|
@ -1,2 +0,0 @@
|
||||
fun a() =
|
||||
1,2,
|
@ -1,26 +0,0 @@
|
||||
fun a() =
|
||||
|
||||
let var a = 1 in 1 end,
|
||||
|
||||
let fun a (c,dvv,d,f,d)=
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as,
|
||||
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end,
|
||||
var a = 10 * "wawawaw"
|
||||
fun b() fun c(a,a,v) in
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
@ -1,26 +0,0 @@
|
||||
fun a() =
|
||||
|
||||
let var a = 1 in 1 end,
|
||||
|
||||
let fun a (c,dvv,d,f,d)=
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as,
|
||||
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
var a = 10 * "wawawaw"
|
||||
fun b(), fun c(a,a,v) in
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
@ -1 +0,0 @@
|
||||
var a = "10" * "msl"
|
@ -1 +0,0 @@
|
||||
var a = "10" * 10
|
@ -1 +0,0 @@
|
||||
fun a(b,1)
|
@ -1,2 +0,0 @@
|
||||
fun a() =
|
||||
nka(aka(a((1 != 2 && 1/a%e+2-f/d*sa = (1 != 2 && 1/a%e+2-f/d*sa)))
|
@ -1,2 +0,0 @@
|
||||
fun a() =
|
||||
a==b==c
|
@ -1 +0,0 @@
|
||||
var a = 10 + "a"
|
@ -1,2 +0,0 @@
|
||||
fun a =
|
||||
1
|
@ -1 +0,0 @@
|
||||
var a = 1 + 1
|
@ -1 +0,0 @@
|
||||
fun a(g,d,d,g,g,f,,gf)
|
@ -1,4 +0,0 @@
|
||||
fun a() =
|
||||
1,
|
||||
2
|
||||
3
|
@ -1,3 +0,0 @@
|
||||
fun a() =
|
||||
1//komentar,
|
||||
2
|
@ -1,6 +0,0 @@
|
||||
fun a() =
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
@ -1,44 +0,0 @@
|
||||
var _kfoai = 8 * "neki"
|
||||
var fkaio92j0a = 1 * 'a'
|
||||
|
||||
fun a (c,dvv,d,f,d)
|
||||
|
||||
fun b() =
|
||||
1
|
||||
|
||||
fun a() =
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as,
|
||||
nka(aka(a(1 != 2 && 1/a%e+2-f/d*sa, (1 != 2 && 1/a%e+2-f/d*sa)))) = 1 != 2 && 1/a%e+2-f/d*sa,
|
||||
nka(aka(a(1 != 2 && 1/a%e+2-f/d*sa, (1 != 2 && 1/a%e+2-f/d*sa))), njc(1+'a')) = 1 != 2 && 1/a%e+2-f/d*sa,
|
||||
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end,
|
||||
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
else
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
||||
,while !+-^+++(a-n()||b==(1 != (2 && 1)/a%(e+a()-2+mkla(a,g,"kof"-"string"%3+'j'&&2))-f/d*sa && osid*'a' < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ do
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
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, 4 * 'a'
|
||||
var f = 1 * 3
|
||||
var g = 1 * 'a'
|
||||
var h = 4 * "aaa"
|
||||
var i =
|
||||
|
||||
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,
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^
|
@ -1,26 +0,0 @@
|
||||
fun a() =
|
||||
|
||||
let var a = 1 in 1 end,
|
||||
|
||||
let fun a (c,dvv,d,f,d)=
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as,
|
||||
|
||||
if !+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^ then
|
||||
mfksa(arg1, arg2) = kdoisk(),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
var a = 10 * "wawawaw"
|
||||
fun b() fun c(a,a,v) in
|
||||
!+-^+++(a||b==(1 != 2 && 1/a%e+2-f/d*sa < (2 && 3) || (1>2) || (1<=2) && 1 >= c))^^^^^,
|
||||
mfksa(arg1, arg2) = kdoisk(a(1)),
|
||||
kajs(a,c,c,1,4,(1+2)&&9^^),
|
||||
a,// komentar
|
||||
_kpofad29-a0as
|
||||
end
|
||||
|
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
for file in *.pins25; do
|
||||
echo "Running $file"
|
||||
java ../../src/pins25/phase/SynAn.java "$file" 2>&1 | tail -n 1
|
||||
printf "\n"
|
||||
done
|
@ -1,2 +1,7 @@
|
||||
fun a() =
|
||||
1 +
|
||||
fun uwu(a) =
|
||||
let
|
||||
var a = 1
|
||||
var b = 2
|
||||
in
|
||||
a + b
|
||||
end
|
1379
src/pins25/common/AST.java
Normal file
1379
src/pins25/common/AST.java
Normal file
File diff suppressed because it is too large
Load Diff
116
src/pins25/phase/Abstr.java
Normal file
116
src/pins25/phase/Abstr.java
Normal file
@ -0,0 +1,116 @@
|
||||
package pins25.phase;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import pins25.common.*;
|
||||
|
||||
/**
|
||||
* Abstraktna sintaksa.
|
||||
*/
|
||||
public class Abstr {
|
||||
|
||||
@SuppressWarnings({"doclint:missing"})
|
||||
public Abstr(SynAn synAn) {
|
||||
throw new Report.InternalError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstraktno sintaksno drevo z dodanimi atributi abstraktne sintakse.
|
||||
* <p>
|
||||
* Dodani atributi:
|
||||
* <ol>
|
||||
* <li>({@link Abstr}) lokacija kode, ki pripada posameznemu vozliscu.</li>
|
||||
* </ol>
|
||||
*/
|
||||
public static class AttrAST extends AST.AttrAST {
|
||||
|
||||
/**
|
||||
* Atribut: lokacija kode, ki priprada posameznemu vozliscu.
|
||||
*/
|
||||
public final Map<AST.Node, Report.Locatable> attrLoc;
|
||||
|
||||
/**
|
||||
* Ustvari novo abstraktno sintaksno drevo z dodanimi atributi abstraktne
|
||||
* sintakse.
|
||||
*
|
||||
* @param attrAST Abstraktno sintaksno drevo.
|
||||
* @param attrLoc Atribut: lokacija kode, ki priprada posameznemu vozliscu.
|
||||
*/
|
||||
public AttrAST(final AST.AttrAST attrAST, final Map<AST.Node, Report.Locatable> attrLoc) {
|
||||
super(attrAST.ast);
|
||||
this.attrLoc = attrLoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ustvari novo abstraktno sintaksno drevo z dodanimi atributi abstraktne
|
||||
* sintakse.
|
||||
*
|
||||
* @param attrAST Abstraktno sintaksno drevo z dodanimi atributi abstraktne
|
||||
* sintakse.
|
||||
*/
|
||||
public AttrAST(final AttrAST attrAST) {
|
||||
super(attrAST.ast);
|
||||
this.attrLoc = attrAST.attrLoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String head(final AST.Node node, final boolean highlighted) {
|
||||
switch (node) {
|
||||
case AST.Nodes<?> nodes:
|
||||
return "";
|
||||
default:
|
||||
final Report.Locatable loc = attrLoc.get(node);
|
||||
return (" ") + (loc == null ? "???" : loc.location().toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* S klicem sintaksnega analizatorja zgradi abstraktno sintaksno drevo.
|
||||
*
|
||||
* @param synAn Sintaksni analizator.
|
||||
* @return Abstraktno sintaksno drevo z dodanimi atributi abstraktne sintakse.
|
||||
*/
|
||||
public static AttrAST constructAST(SynAn synAn) {
|
||||
final HashMap<AST.Node, Report.Locatable> attrLoc = new HashMap<AST.Node, Report.Locatable>();
|
||||
final AST.Node ast = synAn.parse(attrLoc);
|
||||
return new AttrAST(new AST.AttrAST(ast), Collections.unmodifiableMap(attrLoc));
|
||||
}
|
||||
|
||||
// --- ZAGON ---
|
||||
|
||||
/**
|
||||
* Zagon gradnje abstraktnega sintaksnega drevesa kot samostojnega programa.
|
||||
*
|
||||
* @param cmdLineArgs Argumenti v ukazni vrstici.
|
||||
*/
|
||||
public static void main(final String[] cmdLineArgs) {
|
||||
System.out.println("This is PINS'25 compiler (abstract syntax):");
|
||||
|
||||
try {
|
||||
if (cmdLineArgs.length == 0)
|
||||
throw new Report.Error("No source file specified in the command line.");
|
||||
if (cmdLineArgs.length > 1)
|
||||
Report.warning("Unused arguments in the command line.");
|
||||
|
||||
try (final SynAn synAn = new SynAn(cmdLineArgs[0])) {
|
||||
// abstraktna sintaksa:
|
||||
final AttrAST abstrAttrAST = Abstr.constructAST(synAn);
|
||||
|
||||
(new AST.Logger(abstrAttrAST)).log();
|
||||
}
|
||||
|
||||
// Upajmo, da kdaj pridemo to te tocke.
|
||||
// A zavedajmo se sledecega:
|
||||
// 1. Prevod je zaradi napak v programu lahko napacen :-o
|
||||
// 2. Izvorni program se zdalec ni tisto, kar je programer hotel, da bi bil ;-)
|
||||
Report.info("Done.");
|
||||
} catch (Report.Error error) {
|
||||
// Izpis opisa napake.
|
||||
System.err.println(error.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,9 @@ package pins25.phase;
|
||||
|
||||
import pins25.common.*;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sintaksni analizator.
|
||||
@ -14,6 +16,8 @@ public class SynAn implements AutoCloseable {
|
||||
*/
|
||||
private final LexAn lexAn;
|
||||
|
||||
private HashMap<AST.Node, Report.Locatable> attrLoc;
|
||||
|
||||
/**
|
||||
* Ustvari nov sintaksni analizator.
|
||||
*
|
||||
@ -45,158 +49,199 @@ public class SynAn implements AutoCloseable {
|
||||
/**
|
||||
* Opravi sintaksno analizo.
|
||||
*/
|
||||
public void parse() {
|
||||
parseProgram();
|
||||
|
||||
public AST.Node parse(HashMap<AST.Node, Report.Locatable> attrLoc) {
|
||||
this.attrLoc = attrLoc;
|
||||
final AST.Nodes<AST.MainDef> defs = parseProgram();
|
||||
if (lexAn.peekToken().symbol() != Token.Symbol.EOF)
|
||||
Report.warning(lexAn.peekToken(),
|
||||
"Unexpected text '" + lexAn.peekToken().lexeme() + "...' at the end of the program.");
|
||||
return defs;
|
||||
}
|
||||
|
||||
private void parseProgram() {
|
||||
System.out.println("program -> definition restdefs");
|
||||
parseDefinition();
|
||||
parseRestDefinitions();
|
||||
private AST.Nodes<AST.MainDef> parseProgram() {
|
||||
// program -> definition restdefs
|
||||
List<AST.MainDef> defs = new ArrayList<>();
|
||||
|
||||
defs.add(parseDefinition());
|
||||
parseRestDefinitions(defs);
|
||||
|
||||
return new AST.Nodes<>(defs);
|
||||
}
|
||||
|
||||
private void parseRestDefinitions() {
|
||||
private void parseRestDefinitions(List<AST.MainDef> defs) {
|
||||
if (lexAn.peekToken().symbol() != Token.Symbol.EOF) {
|
||||
System.out.println("restdefs -> definition restdefs");
|
||||
parseDefinition();
|
||||
parseRestDefinitions();
|
||||
} else {
|
||||
System.out.println("restdefs -> ε");
|
||||
// restdefs -> definition restdefs
|
||||
defs.add(parseDefinition());
|
||||
parseRestDefinitions(defs);
|
||||
}
|
||||
// restdefs -> ε
|
||||
}
|
||||
|
||||
private void parseDefinition() {
|
||||
private AST.MainDef parseDefinition() {
|
||||
Token token = lexAn.peekToken();
|
||||
switch (token.symbol()) {
|
||||
case FUN:
|
||||
System.out.println("definition -> FUN IDENTIFIER LPAREN parameters RPAREN funcassign");
|
||||
check(Token.Symbol.FUN);
|
||||
check(Token.Symbol.IDENTIFIER);
|
||||
case FUN: {
|
||||
// definition -> FUN IDENTIFIER LPAREN parameters RPAREN funcassign
|
||||
Token fun = check(Token.Symbol.FUN);
|
||||
Token id = check(Token.Symbol.IDENTIFIER);
|
||||
check(Token.Symbol.LPAREN);
|
||||
parseParameters();
|
||||
check(Token.Symbol.RPAREN);
|
||||
parseFunctionAssignment();
|
||||
break;
|
||||
List<AST.ParDef> params = parseParameters();
|
||||
Token rParen = check(Token.Symbol.RPAREN);
|
||||
List<AST.Stmt> stmts = parseFunctionAssignment();
|
||||
|
||||
case VAR:
|
||||
System.out.println("definition -> VAR IDENTIFIER ASSIGN initializers");
|
||||
check(Token.Symbol.VAR);
|
||||
check(Token.Symbol.IDENTIFIER);
|
||||
AST.FunDef funDef = new AST.FunDef(id.lexeme(), params, stmts);
|
||||
attrLoc.put(funDef, new Report.Location(fun, stmts.isEmpty() ? rParen : attrLoc.get(stmts.getLast())));
|
||||
return funDef;
|
||||
}
|
||||
|
||||
case VAR: {
|
||||
// definition -> VAR IDENTIFIER ASSIGN initializers
|
||||
Token var = check(Token.Symbol.VAR);
|
||||
Token id = check(Token.Symbol.IDENTIFIER);
|
||||
check(Token.Symbol.ASSIGN);
|
||||
parseInitializers();
|
||||
break;
|
||||
List<AST.Init> inits = parseInitializers();
|
||||
|
||||
AST.VarDef varDef = new AST.VarDef(id.lexeme(), inits);
|
||||
attrLoc.put(varDef, new Report.Location(var, attrLoc.get(inits.getLast())));
|
||||
return varDef;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected definition.");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseFunctionAssignment() {
|
||||
private List<AST.Stmt> parseFunctionAssignment() {
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.ASSIGN) {
|
||||
System.out.println("funcassign -> ASSIGN statements");
|
||||
// funcassign -> ASSIGN statements
|
||||
check(Token.Symbol.ASSIGN);
|
||||
parseStatements();
|
||||
} else {
|
||||
System.out.println("funcassign -> ε");
|
||||
return parseStatements();
|
||||
}
|
||||
|
||||
// funcassign -> ε
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private void parseParameters() {
|
||||
private List<AST.ParDef> parseParameters() {
|
||||
List<AST.ParDef> defs = new ArrayList<>();
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.IDENTIFIER) {
|
||||
System.out.println("parameters -> IDENTIFIER restparams");
|
||||
check(Token.Symbol.IDENTIFIER);
|
||||
parseRestParameters();
|
||||
} else {
|
||||
System.out.println("parameters -> ε");
|
||||
// parameters -> IDENTIFIER restparams
|
||||
Token id = check(Token.Symbol.IDENTIFIER);
|
||||
AST.ParDef parDef = new AST.ParDef(id.lexeme());
|
||||
attrLoc.put(parDef, id);
|
||||
defs.add(parDef);
|
||||
parseRestParameters(defs);
|
||||
}
|
||||
|
||||
// parameters -> ε
|
||||
|
||||
return defs;
|
||||
}
|
||||
|
||||
private void parseRestParameters() {
|
||||
private void parseRestParameters(List<AST.ParDef> defs) {
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.COMMA) {
|
||||
System.out.println("restparams -> COMMA IDENTIFIER restparams");
|
||||
// restparams -> COMMA IDENTIFIER restparams
|
||||
check(Token.Symbol.COMMA);
|
||||
check(Token.Symbol.IDENTIFIER);
|
||||
parseRestParameters();
|
||||
} else {
|
||||
System.out.println("restparams -> ε");
|
||||
Token id = check(Token.Symbol.IDENTIFIER);
|
||||
AST.ParDef parDef = new AST.ParDef(id.lexeme());
|
||||
attrLoc.put(parDef, id);
|
||||
defs.add(parDef);
|
||||
parseRestParameters(defs);
|
||||
}
|
||||
// restparams -> ε
|
||||
}
|
||||
|
||||
private void parseStatements() {
|
||||
System.out.println("statements -> statement reststmts");
|
||||
parseStatement();
|
||||
parseRestStatements();
|
||||
private List<AST.Stmt> parseStatements() {
|
||||
// statements -> statement reststmts
|
||||
|
||||
List<AST.Stmt> stmts = new ArrayList<>();
|
||||
|
||||
stmts.add(parseStatement());
|
||||
parseRestStatements(stmts);
|
||||
|
||||
return stmts;
|
||||
}
|
||||
|
||||
private void parseExpressionAssign() {
|
||||
private AST.Expr parseExpressionAssign() {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.ASSIGN) {
|
||||
System.out.println("exprassign -> ASSIGN expression");
|
||||
// exprassign -> ASSIGN expression
|
||||
check(Token.Symbol.ASSIGN);
|
||||
parseExpression();
|
||||
} else {
|
||||
System.out.println("exprassign -> ε");
|
||||
return parseExpression();
|
||||
}
|
||||
|
||||
// exprassign -> ε
|
||||
return null;
|
||||
}
|
||||
|
||||
private void parseElseStatement() {
|
||||
private List<AST.Stmt> parseElseStatements() {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.ELSE) {
|
||||
System.out.println("elsestmt -> ELSE statements");
|
||||
// elsestmt -> ELSE statements
|
||||
check(Token.Symbol.ELSE);
|
||||
parseStatements();
|
||||
} else {
|
||||
System.out.println("elsestmt -> ε");
|
||||
return parseStatements();
|
||||
}
|
||||
|
||||
// elsestmt -> ε
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private void parseRestStatements() {
|
||||
private void parseRestStatements(List<AST.Stmt> stmts) {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.COMMA) {
|
||||
System.out.println("reststmts -> COMMA statement reststmts");
|
||||
// reststmts -> COMMA statement reststmts
|
||||
check(Token.Symbol.COMMA);
|
||||
parseStatement();
|
||||
parseRestStatements();
|
||||
} else {
|
||||
System.out.println("reststmts -> ε");
|
||||
stmts.add(parseStatement());
|
||||
parseRestStatements(stmts);
|
||||
}
|
||||
// reststmts -> ε
|
||||
}
|
||||
|
||||
private void parseStatement() {
|
||||
private AST.Stmt parseStatement() {
|
||||
Token token = lexAn.peekToken();
|
||||
switch (token.symbol()) {
|
||||
case IF:
|
||||
System.out.println("statement -> if expression then statements elsestmt end");
|
||||
check(Token.Symbol.IF);
|
||||
parseExpression();
|
||||
case IF: {
|
||||
// statement -> if expression then statements elsestmt end
|
||||
Token ifT = check(Token.Symbol.IF);
|
||||
AST.Expr cond = parseExpression();
|
||||
check(Token.Symbol.THEN);
|
||||
parseStatements();
|
||||
parseElseStatement();
|
||||
check(Token.Symbol.END);
|
||||
break;
|
||||
List<AST.Stmt> thenStmts = parseStatements();
|
||||
List<AST.Stmt> elseStmts = parseElseStatements();
|
||||
Token end = check(Token.Symbol.END);
|
||||
|
||||
case WHILE:
|
||||
System.out.println("statement -> while expression do statements end");
|
||||
check(Token.Symbol.WHILE);
|
||||
parseExpression();
|
||||
AST.IfStmt ifStmt = new AST.IfStmt(cond, thenStmts, elseStmts);
|
||||
attrLoc.put(ifStmt, new Report.Location(ifT, end));
|
||||
return ifStmt;
|
||||
}
|
||||
|
||||
case WHILE: {
|
||||
// statement -> while expression do statements end
|
||||
Token whileT = check(Token.Symbol.WHILE);
|
||||
AST.Expr cond = parseExpression();
|
||||
check(Token.Symbol.DO);
|
||||
parseStatements();
|
||||
check(Token.Symbol.END);
|
||||
break;
|
||||
List<AST.Stmt> stmts = parseStatements();
|
||||
Token end = check(Token.Symbol.END);
|
||||
|
||||
case LET:
|
||||
System.out.println("statement -> let definition reststmtdefs in statements end");
|
||||
check(Token.Symbol.LET);
|
||||
parseDefinition();
|
||||
parseRestStatementDefinitions();
|
||||
AST.WhileStmt whileStmt = new AST.WhileStmt(cond, stmts);
|
||||
attrLoc.put(whileStmt, new Report.Location(whileT, end));
|
||||
return whileStmt;
|
||||
}
|
||||
|
||||
case LET: {
|
||||
// statement -> let definition reststmtdefs in statements end
|
||||
Token let = check(Token.Symbol.LET);
|
||||
List<AST.MainDef> defs = new ArrayList<>();
|
||||
defs.add(parseDefinition());
|
||||
parseRestStatementDefinitions(defs);
|
||||
check(Token.Symbol.IN);
|
||||
parseStatements();
|
||||
check(Token.Symbol.END);
|
||||
break;
|
||||
List<AST.Stmt> stmts = parseStatements();
|
||||
Token end = check(Token.Symbol.END);
|
||||
|
||||
AST.LetStmt letStmt = new AST.LetStmt(defs, stmts);
|
||||
attrLoc.put(letStmt, new Report.Location(let, end));
|
||||
return letStmt;
|
||||
}
|
||||
|
||||
case IDENTIFIER:
|
||||
case LPAREN:
|
||||
@ -207,111 +252,157 @@ public class SynAn implements AutoCloseable {
|
||||
case INTCONST:
|
||||
case CHARCONST:
|
||||
case STRINGCONST:
|
||||
System.out.println("statement -> expression exprassign");
|
||||
parseExpression();
|
||||
parseExpressionAssign();
|
||||
break;
|
||||
// statement -> expression exprassign
|
||||
AST.Expr expr = parseExpression();
|
||||
AST.Expr srcExpr = parseExpressionAssign();
|
||||
if (srcExpr != null) {
|
||||
AST.AssignStmt assignStmt = new AST.AssignStmt(expr, srcExpr);
|
||||
attrLoc.put(assignStmt, new Report.Location(attrLoc.get(expr), attrLoc.get(srcExpr)));
|
||||
return assignStmt;
|
||||
}
|
||||
AST.ExprStmt exprStmt = new AST.ExprStmt(expr);
|
||||
attrLoc.put(exprStmt, attrLoc.get(expr));
|
||||
return exprStmt;
|
||||
|
||||
default:
|
||||
throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected statement.");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseRestStatementDefinitions() {
|
||||
private void parseRestStatementDefinitions(List<AST.MainDef> defs) {
|
||||
switch (lexAn.peekToken().symbol()) {
|
||||
case FUN:
|
||||
case VAR:
|
||||
System.out.println("reststmtdefs -> definition reststmtdefs");
|
||||
parseDefinition();
|
||||
parseRestStatementDefinitions();
|
||||
// reststmtdefs -> definition reststmtdefs
|
||||
defs.add(parseDefinition());
|
||||
parseRestStatementDefinitions(defs);
|
||||
break;
|
||||
|
||||
case IN:
|
||||
System.out.println("reststmtdefs -> ε");
|
||||
// reststmtdefs -> ε
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseInitializers() {
|
||||
private List<AST.Init> parseInitializers() {
|
||||
List<AST.Init> inits = new ArrayList<>();
|
||||
|
||||
switch (lexAn.peekToken().symbol()) {
|
||||
case INTCONST:
|
||||
case CHARCONST:
|
||||
case STRINGCONST:
|
||||
System.out.println("initializers -> initializer restinits");
|
||||
parseInitializer();
|
||||
parseRestInitializers();
|
||||
// initializers -> initializer restinits
|
||||
inits.add(parseInitializer());
|
||||
parseRestInitializers(inits);
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.println("initializers -> ε");
|
||||
// initializers -> ε
|
||||
break;
|
||||
}
|
||||
|
||||
return inits;
|
||||
}
|
||||
|
||||
private void parseInitializer() {
|
||||
private AST.Init parseInitializer() {
|
||||
Token token = lexAn.peekToken();
|
||||
switch (token.symbol()) {
|
||||
case INTCONST:
|
||||
System.out.println("initializer -> INTCONST intconstmult");
|
||||
check(Token.Symbol.INTCONST);
|
||||
parseIntegerConstantMultiplier();
|
||||
break;
|
||||
case INTCONST: {
|
||||
// initializer -> INTCONST intconstmult
|
||||
Token value = check(Token.Symbol.INTCONST);
|
||||
AST.AtomExpr intConst = new AST.AtomExpr(AST.AtomExpr.Type.INTCONST, value.lexeme());
|
||||
attrLoc.put(intConst, value);
|
||||
AST.AtomExpr multConst = parseIntegerConstantMultiplier();
|
||||
if (multConst != null) {
|
||||
AST.Init init = new AST.Init(intConst, multConst);
|
||||
attrLoc.put(init, new Report.Location(value, attrLoc.get(multConst)));
|
||||
return init;
|
||||
}
|
||||
AST.Init init = new AST.Init(
|
||||
new AST.AtomExpr(AST.AtomExpr.Type.INTCONST, "1"),
|
||||
intConst
|
||||
);
|
||||
attrLoc.put(init, value);
|
||||
return init;
|
||||
}
|
||||
|
||||
case CHARCONST:
|
||||
System.out.println("initializer -> CHARCONST");
|
||||
check(Token.Symbol.CHARCONST);
|
||||
break;
|
||||
case CHARCONST: {
|
||||
// initializer -> CHARCONST
|
||||
Token value = check(Token.Symbol.CHARCONST);
|
||||
AST.AtomExpr charConst = new AST.AtomExpr(AST.AtomExpr.Type.CHRCONST, value.lexeme());
|
||||
attrLoc.put(charConst, value);
|
||||
AST.Init init = new AST.Init(
|
||||
new AST.AtomExpr(AST.AtomExpr.Type.INTCONST, "1"),
|
||||
charConst
|
||||
);
|
||||
attrLoc.put(init, value);
|
||||
return init;
|
||||
}
|
||||
|
||||
case STRINGCONST:
|
||||
System.out.println("initializer -> STRINGCONST");
|
||||
check(Token.Symbol.STRINGCONST);
|
||||
break;
|
||||
case STRINGCONST: {
|
||||
// initializer -> STRINGCONST
|
||||
Token value = check(Token.Symbol.STRINGCONST);
|
||||
AST.AtomExpr strConst = new AST.AtomExpr(AST.AtomExpr.Type.STRCONST, value.lexeme());
|
||||
attrLoc.put(strConst, value);
|
||||
AST.Init init = new AST.Init(
|
||||
new AST.AtomExpr(AST.AtomExpr.Type.INTCONST, "1"),
|
||||
strConst
|
||||
);
|
||||
attrLoc.put(init, value);
|
||||
return init;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected constant.");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseRestInitializers() {
|
||||
private void parseRestInitializers(List<AST.Init> inits) {
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.COMMA) {
|
||||
System.out.println("restinits -> COMMA initializer restinits");
|
||||
// restinits -> COMMA initializer restinits
|
||||
check(Token.Symbol.COMMA);
|
||||
parseInitializer();
|
||||
parseRestInitializers();
|
||||
} else {
|
||||
System.out.println("restinits -> ε");
|
||||
inits.add(parseInitializer());
|
||||
parseRestInitializers(inits);
|
||||
}
|
||||
// restinits -> ε
|
||||
}
|
||||
|
||||
private void parseIntegerConstantMultiplier() {
|
||||
private AST.AtomExpr parseIntegerConstantMultiplier() {
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.MUL) {
|
||||
System.out.println("intconstmult -> MUL const");
|
||||
// intconstmult -> MUL const
|
||||
check(Token.Symbol.MUL);
|
||||
parseConstant();
|
||||
} else {
|
||||
System.out.println("intconstmult -> ε");
|
||||
return parseConstant();
|
||||
}
|
||||
// intconstmult -> ε
|
||||
return null;
|
||||
}
|
||||
|
||||
private void parseConstant() {
|
||||
private AST.AtomExpr 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;
|
||||
case INTCONST: {
|
||||
// const -> INTCONST
|
||||
Token value = check(Token.Symbol.INTCONST);
|
||||
AST.AtomExpr atomExpr = new AST.AtomExpr(AST.AtomExpr.Type.INTCONST, value.lexeme());
|
||||
attrLoc.put(atomExpr, value);
|
||||
return atomExpr;
|
||||
}
|
||||
case CHARCONST: {
|
||||
// const -> CHARCONST
|
||||
Token value = check(Token.Symbol.CHARCONST);
|
||||
AST.AtomExpr atomExpr = new AST.AtomExpr(AST.AtomExpr.Type.CHRCONST, value.lexeme());
|
||||
attrLoc.put(atomExpr, value);
|
||||
return atomExpr;
|
||||
}
|
||||
case STRINGCONST: {
|
||||
// const -> STRINGCONST
|
||||
Token value = check(Token.Symbol.STRINGCONST);
|
||||
AST.AtomExpr atomExpr = new AST.AtomExpr(AST.AtomExpr.Type.STRCONST, value.lexeme());
|
||||
attrLoc.put(atomExpr, value);
|
||||
return atomExpr;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected constant.");
|
||||
@ -337,218 +428,324 @@ public class SynAn implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseExpression() {
|
||||
private AST.Expr parseExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("expression -> conjexpr restdisj");
|
||||
parseConjunctionExpression();
|
||||
parseRestDisjunctions();
|
||||
// expression -> conjexpr restdisj
|
||||
AST.Expr left = parseConjunctionExpression();
|
||||
return parseRestDisjunctions(left);
|
||||
}
|
||||
|
||||
private void parseRestDisjunctions() {
|
||||
private AST.Expr parseRestDisjunctions(AST.Expr left) {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.OR) {
|
||||
System.out.println("restdisj -> OR conjexpr restdisj");
|
||||
// restdisj -> OR conjexpr restdisj
|
||||
check(Token.Symbol.OR);
|
||||
parseConjunctionExpression();
|
||||
parseRestDisjunctions();
|
||||
AST.Expr right = parseConjunctionExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.OR, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestDisjunctions(binExpr);
|
||||
} else {
|
||||
// restdisj -> ε
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseConjunctionExpression() {
|
||||
private AST.Expr parseConjunctionExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("conjexpr -> cmpexpr restconj");
|
||||
parseComparisonExpression();
|
||||
parseRestConjunctionExpressions();
|
||||
// conjexpr -> cmpexpr restconj
|
||||
AST.Expr left = parseComparisonExpression();
|
||||
return parseRestConjunctions(left);
|
||||
}
|
||||
|
||||
private void parseRestConjunctionExpressions() {
|
||||
private AST.Expr parseRestConjunctions(AST.Expr left) {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.AND) {
|
||||
System.out.println("restconj -> AND cmpexpr restconj");
|
||||
// restconj -> AND cmpexpr restconj
|
||||
check(Token.Symbol.AND);
|
||||
parseComparisonExpression();
|
||||
parseRestConjunctionExpressions();
|
||||
AST.Expr right = parseComparisonExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.AND, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestConjunctions(binExpr);
|
||||
} else {
|
||||
System.out.println("restconj -> ε");
|
||||
// restconj -> ε
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseComparisonExpression() {
|
||||
private AST.Expr parseComparisonExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("cmpexpr -> addexpr restcmp");
|
||||
parseAdditionExpression();
|
||||
parseRestComparisons();
|
||||
// cmpexpr -> addexpr restcmp
|
||||
AST.Expr left = parseAdditionExpression();
|
||||
return parseRestComparisons(left);
|
||||
}
|
||||
|
||||
private void parseRestComparisons() {
|
||||
private AST.Expr parseRestComparisons(AST.Expr left) {
|
||||
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;
|
||||
case EQU: {
|
||||
// restcmp -> EQU addexpr
|
||||
check(Token.Symbol.EQU);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.EQU, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
case NEQ: {
|
||||
// restcmp -> NEQ addexpr
|
||||
check(Token.Symbol.NEQ);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.EQU, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
case LTH: {
|
||||
// restcmp -> LTH addexpr
|
||||
check(Token.Symbol.LTH);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.LTH, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
case GTH: {
|
||||
// restcmp -> GTH addexpr
|
||||
check(Token.Symbol.GTH);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.GTH, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
case LEQ: {
|
||||
// restcmp -> LEQ addexpr
|
||||
check(Token.Symbol.LEQ);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.LEQ, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
case GEQ: {
|
||||
// restcmp -> GEQ addexpr
|
||||
check(Token.Symbol.GEQ);
|
||||
AST.Expr right = parseAdditionExpression();
|
||||
AST.BinExpr binExpr = new AST.BinExpr(AST.BinExpr.Oper.GEQ, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return binExpr;
|
||||
}
|
||||
|
||||
default:
|
||||
System.out.println("restcmp -> ε");
|
||||
break;
|
||||
// restcmp -> ε
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseAdditionExpression() {
|
||||
private AST.Expr parseAdditionExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("addexpr -> multexpr restadd");
|
||||
parseMultiplicationExpression();
|
||||
parseRestAdditions();
|
||||
// addexpr -> multexpr restadd
|
||||
AST.Expr left = parseMultiplicationExpression();
|
||||
return parseRestAdditions(left);
|
||||
}
|
||||
|
||||
private void parseRestAdditions() {
|
||||
private AST.Expr parseRestAdditions(AST.Expr left) {
|
||||
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;
|
||||
case ADD: {
|
||||
// restadd -> ADD multexpr restadd
|
||||
check(Token.Symbol.ADD);
|
||||
AST.Expr right = parseMultiplicationExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.ADD, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestAdditions(binExpr);
|
||||
}
|
||||
case SUB: {
|
||||
// restadd -> SUN multexpr restadd
|
||||
check(Token.Symbol.SUB);
|
||||
AST.Expr right = parseMultiplicationExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.SUB, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestAdditions(binExpr);
|
||||
}
|
||||
|
||||
default:
|
||||
System.out.println("restadd -> ε");
|
||||
break;
|
||||
// restadd -> ε
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private void parseMultiplicationExpression() {
|
||||
private AST.Expr parseMultiplicationExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("multexpr -> prefixexpr restmult");
|
||||
parsePrefixExpression();
|
||||
parseRestMultiplicationExpressions();
|
||||
// multexpr -> prefixexpr restmult
|
||||
AST.Expr left = parsePrefixExpression();
|
||||
return parseRestMultiplicationExpressions(left);
|
||||
}
|
||||
|
||||
private void parseRestMultiplicationExpressions() {
|
||||
private AST.Expr parseRestMultiplicationExpressions(AST.Expr left) {
|
||||
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;
|
||||
case MUL: {
|
||||
// restmult -> MUL prefixexpr restmult
|
||||
check(Token.Symbol.MUL);
|
||||
AST.Expr right = parseMultiplicationExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.MUL, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestMultiplicationExpressions(binExpr);
|
||||
}
|
||||
case DIV: {
|
||||
// restmult -> DIV prefixexpr restmult
|
||||
check(Token.Symbol.DIV);
|
||||
AST.Expr right = parseMultiplicationExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.DIV, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestMultiplicationExpressions(binExpr);
|
||||
}
|
||||
case MOD: {
|
||||
// restmult -> MOD prefixexpr restmult
|
||||
check(Token.Symbol.MOD);
|
||||
AST.Expr right = parseMultiplicationExpression();
|
||||
AST.Expr binExpr = new AST.BinExpr(AST.BinExpr.Oper.MOD, left, right);
|
||||
attrLoc.put(binExpr, new Report.Location(attrLoc.get(left), attrLoc.get(right)));
|
||||
return parseRestMultiplicationExpressions(binExpr);
|
||||
}
|
||||
|
||||
default:
|
||||
System.out.println("restmult -> ε");
|
||||
break;
|
||||
// restmult -> ε
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
private void parsePrefixExpression() {
|
||||
private AST.Expr parsePrefixExpression() {
|
||||
checkExpression();
|
||||
|
||||
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;
|
||||
case ADD: {
|
||||
// prefixexpr -> ADD prefixexpr
|
||||
Token add = check(Token.Symbol.ADD);
|
||||
AST.Expr prefixExpr = parsePrefixExpression();
|
||||
AST.UnExpr unExpr = new AST.UnExpr(AST.UnExpr.Oper.ADD, prefixExpr);
|
||||
attrLoc.put(unExpr, new Report.Location(add, attrLoc.get(prefixExpr)));
|
||||
return unExpr;
|
||||
}
|
||||
case SUB: {
|
||||
// prefixexpr -> SUB prefixexpr
|
||||
Token sub = check(Token.Symbol.SUB);
|
||||
AST.Expr prefixExpr = parsePrefixExpression();
|
||||
AST.UnExpr unExpr = new AST.UnExpr(AST.UnExpr.Oper.SUB, prefixExpr);
|
||||
attrLoc.put(unExpr, new Report.Location(sub, attrLoc.get(prefixExpr)));
|
||||
return unExpr;
|
||||
}
|
||||
case NOT: {
|
||||
// prefixexpr -> NOT prefixexpr
|
||||
Token not = check(Token.Symbol.NOT);
|
||||
AST.Expr prefixExpr = parsePrefixExpression();
|
||||
AST.UnExpr unExpr = new AST.UnExpr(AST.UnExpr.Oper.NOT, prefixExpr);
|
||||
attrLoc.put(unExpr, new Report.Location(not, attrLoc.get(prefixExpr)));
|
||||
return unExpr;
|
||||
}
|
||||
case PTR: {
|
||||
// prefixexpr -> PTR prefixexpr
|
||||
Token ptr = check(Token.Symbol.PTR);
|
||||
AST.Expr prefixExpr = parsePrefixExpression();
|
||||
AST.UnExpr unExpr = new AST.UnExpr(AST.UnExpr.Oper.MEMADDR, prefixExpr);
|
||||
attrLoc.put(unExpr, new Report.Location(ptr, attrLoc.get(prefixExpr)));
|
||||
return unExpr;
|
||||
}
|
||||
|
||||
default:
|
||||
System.out.println("prefixexpr -> postfixexpr");
|
||||
parsePostfixExpression();
|
||||
break;
|
||||
// prefixexpr -> postfixexpr
|
||||
return parsePostfixExpression();
|
||||
}
|
||||
}
|
||||
|
||||
private void parsePostfixExpression() {
|
||||
private AST.Expr parsePostfixExpression() {
|
||||
checkExpression();
|
||||
|
||||
System.out.println("postfixexpr -> primary postfixop");
|
||||
parsePrimary();
|
||||
parsePostfixOperator();
|
||||
// postfixexpr -> primary postfixop
|
||||
AST.Expr inner = parsePrimary();
|
||||
return parsePostfixOperator(inner);
|
||||
}
|
||||
|
||||
private void parsePostfixOperator() {
|
||||
private AST.Expr parsePostfixOperator(AST.Expr inner) {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.PTR) {
|
||||
System.out.println("postfixop -> PTR postfixop");
|
||||
check(Token.Symbol.PTR);
|
||||
parsePostfixOperator();
|
||||
} else {
|
||||
System.out.println("postfixop -> ε");
|
||||
// postfixop -> PTR postfixop
|
||||
Token ptr = check(Token.Symbol.PTR);
|
||||
AST.UnExpr unExpr = new AST.UnExpr(AST.UnExpr.Oper.VALUEAT, inner);
|
||||
attrLoc.put(unExpr, new Report.Location(attrLoc.get(inner), ptr));
|
||||
return parsePostfixOperator(unExpr);
|
||||
}
|
||||
// postfixop -> ε
|
||||
return inner;
|
||||
}
|
||||
|
||||
private void parsePrimary() {
|
||||
private AST.Expr parsePrimary() {
|
||||
Token token = lexAn.peekToken();
|
||||
switch (token.symbol()) {
|
||||
case IDENTIFIER:
|
||||
System.out.println("primary -> IDENTIFIER exprargs");
|
||||
check(Token.Symbol.IDENTIFIER);
|
||||
parseExpressionArguments();
|
||||
break;
|
||||
// primary -> IDENTIFIER exprargs
|
||||
Token id = check(Token.Symbol.IDENTIFIER);
|
||||
List<AST.Expr> args = parseExpressionArguments();
|
||||
if (args != null) {
|
||||
AST.CallExpr callExpr = new AST.CallExpr(id.lexeme(), args);
|
||||
attrLoc.put(callExpr, new Report.Location(id, attrLoc.get(args.getLast())));
|
||||
return callExpr;
|
||||
}
|
||||
AST.VarExpr varExpr = new AST.VarExpr(id.lexeme());
|
||||
attrLoc.put(varExpr, id);
|
||||
return varExpr;
|
||||
|
||||
case LPAREN:
|
||||
System.out.println("primary -> LPAREN expression RPAREN");
|
||||
// primary -> LPAREN expression RPAREN
|
||||
check(Token.Symbol.LPAREN);
|
||||
parseExpression();
|
||||
AST.Expr expr = parseExpression();
|
||||
check(Token.Symbol.RPAREN);
|
||||
break;
|
||||
return expr;
|
||||
|
||||
case INTCONST:
|
||||
case CHARCONST:
|
||||
case STRINGCONST:
|
||||
System.out.println("primary -> const");
|
||||
parseConstant();
|
||||
break;
|
||||
// primary -> const
|
||||
return parseConstant();
|
||||
|
||||
default:
|
||||
throw new Report.Error(token, "Unexpected symbol '" + token.lexeme() + "', expected identifier, constant or '('.");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseExpressionArguments() {
|
||||
private List<AST.Expr> parseExpressionArguments() {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.LPAREN) {
|
||||
System.out.println("exprargs -> LPAREN arguments RPAREN");
|
||||
// exprargs -> LPAREN arguments RPAREN
|
||||
check(Token.Symbol.LPAREN);
|
||||
parseArguments();
|
||||
List<AST.Expr> args = parseArguments();
|
||||
check(Token.Symbol.RPAREN);
|
||||
} else {
|
||||
System.out.println("exprargs -> ε");
|
||||
return args;
|
||||
}
|
||||
|
||||
// exprargs -> ε
|
||||
return null;
|
||||
}
|
||||
|
||||
private void parseArguments() {
|
||||
private List<AST.Expr> parseArguments() {
|
||||
List<AST.Expr> args = new ArrayList<>();
|
||||
|
||||
Token token = lexAn.peekToken();
|
||||
if (token.symbol() == Token.Symbol.RPAREN) {
|
||||
System.out.println("arguments -> ε");
|
||||
} else {
|
||||
System.out.println("arguments -> expression restargs");
|
||||
parseExpression();
|
||||
parseRestArguments();
|
||||
// arguments -> ε
|
||||
return args;
|
||||
}
|
||||
// arguments -> expression restargs
|
||||
args.add(parseExpression());
|
||||
parseRestArguments(args);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
private void parseRestArguments() {
|
||||
private void parseRestArguments(List<AST.Expr> args) {
|
||||
if (lexAn.peekToken().symbol() == Token.Symbol.COMMA) {
|
||||
System.out.println("restargs -> COMMA restargs");
|
||||
// restargs -> COMMA restargs
|
||||
check(Token.Symbol.COMMA);
|
||||
parseExpression();
|
||||
parseRestArguments();
|
||||
} else {
|
||||
System.out.println("restargs -> ε");
|
||||
args.add(parseExpression());
|
||||
parseRestArguments(args);
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,7 +767,7 @@ public class SynAn implements AutoCloseable {
|
||||
Report.warning("Unused arguments in the command line.");
|
||||
|
||||
try (SynAn synAn = new SynAn(cmdLineArgs[0])) {
|
||||
synAn.parse();
|
||||
synAn.parse(new HashMap<>());
|
||||
}
|
||||
|
||||
// Upajmo, da kdaj pridemo to te tocke.
|
||||
|
Loading…
x
Reference in New Issue
Block a user