-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.cpp
173 lines (142 loc) · 6.34 KB
/
parser.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//
// mandatory meaningless header
// (c) friol 2023
//
// will *have* to support the following:
// liaison is dynamically typed (and variables can't change type)
// we have implicit variable declaration, despite what "crafting interpreters" says
// plain return without value // DONE
// monodimensional array sorting // DONE
// arr[x].function()
// conditions with only booleans
// if else if come on
// convert function list to function hashmap
// globals (yep) (but only if they start with 'glb') // DONE
// allow v[x].length // DONE
// do this with infinite level of indirection
// circuit breaking if statements with &&
// convert (almost) all the assertions to ifs
// check if evaluating a function calls it two times // DONE
// convert arraylist to expression list // DONE
// foreach iterated is an Expression // DONE
// one-line comments // DONE
// multi-line comments // DONE
// variable initialization -> a=2, b="string", c=-2, d=0.5, e=3*2, f=[]
// dictionaries // DONE
// complex expressions (mathematical) // DONE
// logical expressions (and, or, etc.) // DONE
// strings will have default properties/functions like s.length // DONE
// d.keys for dictionaries // DONE
// main function declaration, in the form of fn main(params) // DONE
// input parameters to main // DONE
// general function declaration, in the form of fn funName(p1,p2,p3) // DONE
// print function included by default // DONE
// variadic print function // DONE
// add (add element to array) function // DONE
// find (find in array) function // DONE
// split function // DONE
// function call with parameters // DONE
// if/else statement // DONE
// return statement // DONE
// while statement // DONE
// for cycle
// foreach v in array (with arrays and strings) // DONE
// readTextFileLineByLine function (returns an array of strings) // DONE
// toInteger function (converts a string to an int) // DONE
// variable increment // DONE
// variable decrement // DONE
// variable *= // DONE
// >>= operator (integer division by 2 AKA right shift) // DONE
// the ability to solve AOC problems, at least up to day 14
// many other things that don't come to mind at the moment
//
#include "parser.h"
liaParser::liaParser()
{
// instantiate your grammar here
auto grammar=(R"(
LiaProgram <- ( TopLevelStmt )*
TopLevelStmt <- FuncDeclStmt / SingleLineCommentStmt / MultiLineCommentStmt / GlobalVarDecl / EndLine
Stmt <- IfStmt / FuncCallStmt / VarDeclStmt / SingleLineCommentStmt / MultiLineCommentStmt / IncrementStmt / DecrementStmt / VarFuncCallStmt /
RshiftStmt / LshiftStmt / MultiplyStmt / LogicalAndStmt / LogicalOrStmt / WhileStmt / ForeachStmt / ReturnStmt / ArrayAssignmentStmt /
DivideStmt / ModuloStmt / EndLine
CodeBlock <- [ \t]* '{' ( Stmt )* [ \t]* '}'
SingleLineCommentStmt <- [ \t]* '//' [^\r\n]* EndLine
MultiLineCommentStmt <- [ \t]* '/*' [^*/]* '*/' EndLine
GlobalVarDecl <- [ \t]* VariableName '=' Expression ';' EndLine?
IfStmt <- [ \t]* 'if' '(' Condition ')' [\r\n]? CodeBlock '\n' ('else' [\r\n]? CodeBlock)?
IncrementStmt <- [ \t]* (ArraySubscript / VariableName) '+=' Expression ';' EndLine?
DecrementStmt <- [ \t]* VariableName '-=' Expression ';' EndLine?
RshiftStmt <- [ \t]* VariableName '>>=' Expression ';' EndLine?
LshiftStmt <- [ \t]* VariableName '<<=' Expression ';' EndLine?
MultiplyStmt <- [ \t]* VariableName '*=' Expression ';' EndLine?
DivideStmt <- [ \t]* VariableName '/=' Expression ';' EndLine?
ModuloStmt <- [ \t]* VariableName '%=' Expression ';' EndLine?
LogicalAndStmt <- [ \t]* VariableName '&=' Expression ';' EndLine?
LogicalOrStmt <- [ \t]* VariableName '|=' Expression ';' EndLine?
WhileStmt <- [ \t]* 'while' '(' Condition ')' [\r\n]? CodeBlock
ForeachStmt <- [ \t]* 'foreach' '(' VariableName 'in' Expression ')' [\r\n]? CodeBlock
Condition <- InnerCondition ( CondOperator Condition )*
InnerCondition <- Expression Relop Expression / '(' Condition ')'
CondOperator <- '&&' / '||'
Relop <- '==' / '<=' / '<' / '>=' / '>' / '!='
FuncDeclStmt <- 'fn' FuncName '(' ( FuncParamList )* ')' [\r\n]? CodeBlock
FuncParamList <- FuncParam ( ',' FuncParam )*
FuncParam <- < [a-zA-Z][0-9a-zA-Z_]* >
VarFuncCallStmt <- [ \t]* VariableName '.' FuncName '(' ( ArgList )* ')' ';' EndLine?
ArrayAssignmentStmt <- [ \t]* ArraySubscript '=' Expression ';' EndLine?
VarDeclStmt <- [ \t]* VariableName '=' Expression ';' EndLine?
VariableName <- < [a-zA-Z][0-9a-zA-Z_]* >
Expression <- InnerExpression ( ExprOperator InnerExpression )*
InnerExpression <- BooleanConst / LongNumber / IntegerNumber / StringLiteral / ArrayInitializer / DictInitializer / RFuncCall /
VariableWithProperty / BitwiseNot / VariableWithFunction / ArraySubscript / VariableName / '(' Expression ')'
ExprOperator <- '+' / '-' / '*' / '/'
BooleanConst <- < 'true' > / < 'false' >
IntegerNumber <- < ('-')?[0-9]+ >
LongNumber <- < ('-')?[0-9]+[L] >
StringLiteral <- < '\"' [^\r\n\"]* '\"' >
ArrayInitializer <- '[' ExpressionList? ']'
DictInitializer <- '{' (DictList)* '}'
BitwiseNot <- '~' Expression
DictList <- KeyValueList
KeyValueList <- StringLiteral ':' Expression (',' StringLiteral ':' Expression)*
ExpressionList <- Expression (',' Expression)*
ArraySubscript <- VariableName '[' Expression ']' ('[' Expression ']')*
VariableWithProperty <- VariableName '.' Property / ArraySubscript '.' Property
Property <- 'length' / 'keys'
VariableWithFunction <- VariableName '.' FuncName '(' ( ArgList )* ')'
FuncCallStmt <- [ \t]* FuncName '(' ( ArgList )* ')' ';' EndLine?
RFuncCall <- [ \t]* FuncName '(' ( ArgList )* ')'
FuncName <- < [a-zA-Z_][0-9a-zA-Z_]* >
ArgList <- ('byref')? Expression ( ',' ('byref')? Expression )*
ReturnStmt <- [ \t]* 'return' Expression? ';' EndLine?
EndLine <- [ \t]* [\r\n]
%whitespace <- [ \t]*
)");
pegParser = new peg::parser();
pegParser->set_logger([](size_t line, size_t col, const std::string& msg, const std::string& rule)
{
std::cerr << line << ":" << col << ": " << msg << "\n";
});
auto grammarIsOk = pegParser->load_grammar(grammar);
if (!grammarIsOk)
{
std::cout << "Error: grammar loading failed." << std::endl;
}
assert(grammarIsOk);
}
int liaParser::parseCode(std::string c)
{
pegParser->enable_ast();
localCode = c;
if (!pegParser->parse(localCode.c_str(), theAst))
{
std::cout << "liaison was unable to parse the provided code." << std::endl;
return 1;
}
return 0;
}
liaParser::~liaParser()
{
delete(pegParser);
}