Made progress on the AST

main
channa 10 months ago
parent 32d290b743
commit 705249bfae

@ -0,0 +1,87 @@
module AST
data AProgram(loc src = |tmp:///|)
= program(AId id, list[AConst] consts, list[AVar] vars, list[ASubProg] subProgs, ABlock main)
;
data AConst(loc src = |tmp:///|)
= const(AId id, AType \type, AValue \value)
;
data AVar(loc src = |tmp:///|)
= var(AId id, AType \type)
;
data ASubProg(loc src = |tmp:///|)
= function(AId id, list[AParam] parameters, AType \returnType, list[AVar] locals, ABlock body)
| procedure(AId id, list[AParam] parameters, list[AVar] locals, ABlock body)
;
data AParam(loc src = |tmp:///|)
= referenceParam(AId id, AType \type)
| valueParam(AId id, AType \type)
;
data AType(loc src = |tmp:///|)
= simpleType(ABasicType \basic)
| arrayType(ABasicType \basic)
;
data ABasicType(loc src = |tmp:///|)
= integerType()
| realType()
;
data ABlock(loc src = |tmp:///|)
= block(list[AStatement] body)
;
data AStatement(loc src = |tmp:///|)
= assignment(ALhs lhs, AExpr res)
| call(ASubProgCall subProg)
| skip()
| blockStatement(ABlock block)
| \if(AGuard guard, AStatement ifBody, AStatement elseBody)
| \while(AGuard guard, AStatement body)
;
data ASubProgCall(loc src = |tmp:///|)
= call(AId id, list[AExpr] args)
| readln(list[AId] ids)
| writeln(list[AExpr] args)
;
data AGuard(loc src = |tmp:///|)
= lessThan(AExpr left, AExpr right)
| lessThanEqual(AExpr left, AExpr right)
| greaterThan(AExpr left, AExpr right)
| greaterThanEqual(AExpr left, AExpr right)
| equal(AExpr left, AExpr right)
| not(AGuard inner)
| and(AGuard left, AGuard right)
| or(AGuard left, AGuard right)
;
data ALhs(loc src = |tmp:///|)
= simple(AId id)
| indexed(AId id, AExpr index)
;
data AExpr(loc src = |tmp:///|)
= ref(AId id)
| index(AId id, AExpr index)
| slice(AId id, AExpr \start, AExpr end)
| val(AValue val)
| call(list[AExpr] args)
| add(AExpr left, AExpr right)
| sub(AExpr left, AExpr right)
| mul(AExpr left, AExpr right)
| div(AExpr left, AExpr right)
| \mod(AExpr left, AExpr right)
| intDiv(AExpr left, AExpr right)
| negate(AExpr inner)
;
data AValue(loc src = |tmp:///|)
= integer(int n)
| \real(real n)
;
data AId(loc src = |tmp:///|)
= id(str name);

@ -0,0 +1,118 @@
module CST2AST
import Syntax;
import AST;
import String;
import Exception;
// TODO: Add source
// -------------------------------- Top level program -----------------------
AProgram cst2ast(start[Program] program) {
// Remove layout
Program p = program.top;
return cst2ast(p);
}
AProgram cst2ast(Program p)
= program(
cst2ast(p.name),
cst2ast(p.consts),
cst2ast(p.vars),
cst2ast(p.subProgs),
cst2ast(p.main)
);
AId cst2ast(Id name)
= id("<name>");
// -------------------------------------- Declarations -----------------------
list[AConst] cst2ast(ConstDecl* consts)
= [cst2ast(const) | const <- consts];
AConst cst2ast(ConstDecl cDecl)
= const(cst2ast(cDecl.id), inferType(cDecl.\value), cst2ast(cDecl.\value));
list[AVar] cst2ast(VarDecl* varDecls)
= [aVar | varDecl <- varDecls, aVar <- cst2ast(varDecl)];
list[AVar] cst2ast(VarDecl varDecl)
= [var(cst2ast(id), cst2ast(varDecl.\type)) | id <- varDecl.ids];
list[ASubProg] cst2ast(SubProgDecl* subProgs)
= [cst2ast(subProg) | subProg <- subProgs];
ASubProg cst2ast((SubProgDecl)`<FunctionDecl f>`)
= function(
cst2ast(f.id),
cst2ast(f.params),
simpleType(cst2ast(f.returnType)),
cst2ast(f.locals),
cst2ast(f.body)
);
ASubProg cst2ast((SubProgDecl)`<ProcedureDecl p>`)
= procedure(
cst2ast(p.id),
cst2ast(p.params),
cst2ast(p.locals),
cst2ast(p.body)
);
list[AParam] cst2ast(Parameters? optParams)
= [param | params <- optParams, param <- cst2ast(params)];
list[AParam] cst2ast(Parameters params);
// ---------------------------- Statement lists -----------------------------
ABlock cst2ast(CompoundStatement body)
= block([
aStatement
| statementList <- body.statementList,
aStatement <- cst2ast(statementList)
]);
list[AStatement] cst2ast(StatementList sList)
= [cst2ast(sList.first)]
+ [cst2ast(statement) | item <- sList.rest, /Statement statement := item];
// ----------------------------- Statements ----------------------------------
AStatement cst2ast((Statement)`<Lhs lhs> := <Expr e>`)
= assignment(cst2ast(lhs), cst2ast(e));
AStatement cst2ast((Statement)`<SubProgCall subProgCall>`)
= call(cst2ast(subProgCall));
AStatement cst2ast((Statement)`<CompoundStatement compoundStatement>`)
= blockStatement(cst2ast(compoundStatement));
AStatement cst2ast((Statement)`skip`)
= skip();
AStatement cst2ast((Statement)`if <Guard g> then <Statement ifStmt> else <Statement elseStmt>`)
= \if(cst2ast(g), cst2ast(ifStmt), cst2ast(elseStmt));
AStatement cst2ast((Statement)`while <Guard g> do <Statement body>`)
= \while(cst2ast(g), cst2ast(body));
// -------------------------------- Calls ------------------------------------
ASubProgCall cst2ast(SubProgCall call);
// --------------------------------- Lhs ------------------------------------
ALhs cst2ast(Lhs lhs);
// ------------------------------ Expressions --------------------------------
AExpr cst2ast(Expr e);
AGuard cst2ast(Guard g);
AValue cst2ast((Number)`<Integer n>`) = integer(toInt("<n>"));
AValue cst2ast((Number)`<Real n>`) = \real(toReal("<n>"));
// ----------------------------- Types ---------------------------------------
AType cst2ast(TypeSpec \type);
ABasicType cst2ast(BasicType \type);
AType inferType((Number)`<Integer _>`) = simpleType(integerType());
AType inferType((Number)`<Real _>`) = simpleType(realType());

@ -10,20 +10,20 @@ extend lang::std::ASCII;
/* /*
A program consists of an id, followed by declarations followed by its body A program consists of an id, followed by declarations followed by its body
*/ */
start syntax Program = 'program' Id ";" ConstDecl* VarDecl* SubProgDecl* CompoundStatement "." start syntax Program = 'program' Id name ";" ConstDecl* consts VarDecl* vars SubProgDecl* subProgs CompoundStatement main "."
; ;
/* /*
A constant's type is implicit by the value it's assigned A constant's type is implicit by the value it's assigned
*/ */
syntax ConstDecl = 'const' Id "=" Number ";" syntax ConstDecl = 'const' Id id "=" Number value ";"
; ;
/* /*
You can declare multiple variables of the same type, in a simple declaration You can declare multiple variables of the same type, in a simple declaration
*/ */
syntax VarDecl = 'var' IdList ":" TypeSpec ";" syntax VarDecl = 'var' IdList ids ":" TypeSpec type ";"
; ;
syntax IdList = Id ("," Id)* syntax IdList = Id ("," Id)*
@ -48,8 +48,11 @@ syntax BasicType = 'integer' | 'real'
Also note that we use SubProg to refer to both functions / procedures. Also note that we use SubProg to refer to both functions / procedures.
*/ */
syntax SubProgDecl = 'function' Id Parameters ":" BasicType ";" VarDecl* CompoundStatement ";" syntax SubProgDecl = FunctionDecl | ProcedureDecl
| 'procedure' Id Parameters? ";" VarDecl* CompoundStatement ";" ;
syntax FunctionDecl = 'function' Id id Parameters params ":" BasicType returnType ";" VarDecl* locals CompoundStatement body";"
;
syntax ProcedureDecl = 'procedure' Id id Parameters? params ";" VarDecl* locals CompoundStatement body ";"
; ;
syntax Parameters = "(" ParameterList ")" syntax Parameters = "(" ParameterList ")"
@ -66,9 +69,11 @@ syntax ParameterList = ParamList (";" ParamList)*;
syntax ParamList = 'var'? IdList ":" TypeSpec syntax ParamList = 'var'? IdList ":" TypeSpec
; ;
syntax CompoundStatement = 'begin' StatementList? 'end'; syntax CompoundStatement = 'begin' StatementList? statementList 'end'
;
syntax StatementList = Statement (";" Statement)*; syntax StatementList = Statement first (";" Statement)* rest
;
/* /*
We have: We have:
1. Assignment statements 1. Assignment statements
@ -146,21 +151,28 @@ lexical Id = ([a-z A-Z 0-9 _] !<< [a-z A-Z][a-z A-Z 0-9 _]* !>> [a-z A-Z
/* /*
Note that equality is represented as = and inequality is represented as <> Note that equality is represented as = and inequality is represented as <>
*/ */
lexical Relop = "\<"|"\<="|"\>"|"\>="|"="|"\<\>"; lexical Relop = "\<"|"\<="|"\>"|"\>="|"="|"\<\>"
;
/* /*
Either: Either:
1. A series of digits (integer) 1. Integer: A series of digits
2. An optional characteristic (right of the ".") and a mandatory mantissa (left of the ".") 2. Real: An optional characteristic (right of the ".") and a mandatory
mantissa (left of the ".")
This allows both .1 and 0.1 This allows both .1 and 0.1
*/ */
lexical Number = Digit+ lexical Number = Integer
| Digit* "." Digit+ | Real
;
lexical Integer = Digit+
;
lexical Real = Digit* "." Digit+
; ;
/* /*
A comment is anything between a "{" and a "}" A comment is anything between a "{" and a "}"
*/ */
lexical Comment = "{" ![}]* "}"; lexical Comment = "{" ![}]* "}"
;
/* /*
Layout essentially captures all characters between our main syntactic objects. You can read this as follows: Layout essentially captures all characters between our main syntactic objects. You can read this as follows:
@ -194,7 +206,8 @@ lexical Comment = "{" ![}]* "}";
This is also in the documentation. See: https://www.rascal-mpl.org/docs/Rascal/Declarations/SyntaxDefinition/Disambiguation/Follow/ This is also in the documentation. See: https://www.rascal-mpl.org/docs/Rascal/Declarations/SyntaxDefinition/Disambiguation/Follow/
*/ */
layout Standard layout Standard
= WhitespaceOrComment* !>> [\u0009-\u000D \u0020 \u0085 \u00A0 \u1680 \u180E \u2000-\u200A \u2028 \u2029 \u202F \u205F \u3000 {}]; = WhitespaceOrComment* !>> [\u0009-\u000D \u0020 \u0085 \u00A0 \u1680 \u180E \u2000-\u200A \u2028 \u2029 \u202F \u205F \u3000 {}]
;
lexical WhitespaceOrComment lexical WhitespaceOrComment
= whitespace: Whitespace = whitespace: Whitespace

@ -4,6 +4,7 @@ import ParseTree;
import Exception; import Exception;
import Syntax; import Syntax;
import IO; import IO;
import vis::Text;
void main() { void main() {
// The input files // The input files
@ -17,6 +18,15 @@ void main() {
} }
} }
void testRobinProgram() {
loc robinLoc = |project://minipas/test/input/robin.pas|;
loc outLoc = |project://minipas/target/out/robinTree.txt|;
start[Program] parseTree = parse(#start[Program], robinLoc);
str printedTree = prettyTree(parseTree);
writeFile(outLoc, printedTree);
}
/* /*
Parses the file Parses the file
*/ */

@ -0,0 +1,26 @@
program robin;
const cover = 1;
const robins_skill = 0;
const dogukan = 2;
var player : integer;
{ Prints 1 if Robin wins, 0 if it's a draw, -1 if robin loses }
procedure smash(at : integer; opponents_skill : integer) ;
BEGIN
if (robins_skill > opponents_skill) then
writeln(1)
else
if (robins_skill = opponents_skill) then
writeln(0)
else
writeln(-1)
END;
BEGIN
player := dogukan;
smash(cover, player)
END.
Loading…
Cancel
Save