This commit is contained in:
Gašper Dobrovoljc 2025-03-31 22:55:57 +02:00
parent a4773edb76
commit a8f08725aa
No known key found for this signature in database
GPG Key ID: 0E7E037018CFA5A5
32 changed files with 1960 additions and 493 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
out/
**/.DS_Store
*.zip

1
.idea/misc.xml generated
View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12" />

View File

@ -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>

View File

@ -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))^^^^^

View File

@ -1,4 +0,0 @@
fun a() =
while 1 then
neki
end

View File

@ -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

View File

@ -1 +0,0 @@
fun a() =

View File

@ -1,2 +0,0 @@
fun a() =
1,2,

View File

@ -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

View File

@ -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

View File

@ -1 +0,0 @@
var a = "10" * "msl"

View File

@ -1 +0,0 @@
var a = "10" * 10

View File

@ -1 +0,0 @@
fun a(b,1)

View File

@ -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)))

View File

@ -1,2 +0,0 @@
fun a() =
a==b==c

View File

@ -1 +0,0 @@
var a = 10 + "a"

View File

@ -1,2 +0,0 @@
fun a =
1

View File

@ -1 +0,0 @@
var a = 1 + 1

View File

View File

@ -1 +0,0 @@
fun a(g,d,d,g,g,f,,gf)

View File

@ -1,4 +0,0 @@
fun a() =
1,
2
3

View File

@ -1,3 +0,0 @@
fun a() =
1//komentar,
2

View File

@ -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

View File

@ -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

View File

@ -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))^^^^^

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

116
src/pins25/phase/Abstr.java Normal file
View 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);
}
}
}

View File

@ -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.

1
zip.sh
View File

@ -7,5 +7,6 @@ mkdir pins25
rsync -av --exclude=".*" ./src ./pins25
rsync -av --exclude=".*" --exclude="*.pins" ./prg ./pins25
rm ./pins25/prg/*.pins
rm 63230048-"$phase".zip
zip -r 63230048-"$phase".zip ./pins25
rm -rf ./pins25