6 const int EQUATE_PREC
= 2;
7 const int MSG_PREC
= 4;
8 const int COMMA_GROUP_PREC
= 5;
9 const int SCOPE_PREC
= 6;
10 const int COMPARE_PREC
= 10;
11 const int ADD_SUB_PREC
= 20;
12 const int MULT_DIV_PREC
= 30;
13 const int POWER_PREC
= 40;
15 TypeInfo
parse_typesig(std::vector
<Token
*>::iterator
&iter
,
16 std::vector
<Token
*>::iterator
&end
) {
20 throw CompilerException("Incomplete type signature", *(--iter
));
22 ti
.declType
= (*iter
)->data
;
26 if ((*iter
)->data
== "[") {
29 throw CompilerException("Incomplete type signature", *(--iter
));
31 if ((*iter
)->data
!= "]") {
32 throw CompilerException("Unsupported type signature", *(--iter
));
35 ti
.containerType
= ContainerType::Array
;
37 TypeInfo containedType
;
38 containedType
.declType
= ti
.declType
;
39 containedType
.containerType
= ContainerType::Scalar
;
40 ti
.containedTypes
.push_back(containedType
);
44 throw CompilerException("Incomplete type signature", *(--iter
));
50 VarDeclExprAST
* parse_variable_decl(std::vector
<Token
*>::iterator
&iter
,
51 std::vector
<Token
*>::iterator
&end
) {
56 VariableInfo
*vi
= new VariableInfo();
57 VarDeclExprAST
*returnVal
= NULL
;
60 throw CompilerException("Expected variable declaration", *(--iter
));
63 if ((*iter
)->data
== "var") {
67 //FIXME: this is the _old_ style
68 else if ((*iter
)->data
== "spawn") {
72 else if ((*iter
)->data
== "new") {
77 vi
->type
= parse_typesig(iter
, end
);
78 if ((*iter
)->tokenType
!= TokenType::Id
) {
79 std::ostringstream msg
;
80 msg
<< "Invalid variable declaration for '" << (*iter
)->data
<< "'";
81 throw CompilerException(msg
.str(), *iter
);
82 //throw CompilerException("Invalid variable declaration", *(iter));
84 vi
->name
= (*iter
)->data
;
86 returnVal
= new VarDeclExprAST(vi
, isSpawn
, isAlloc
);
87 returnVal
->filepos
= (*iter
)->pos
;
91 if ((*iter
)->data
== "[") {
94 throw CompilerException("Incomplete default size", *(--iter
));
96 vi
->size
= parse_expression(iter
, end
);
98 vi->type.containerType = ContainerType::Array;
100 TypeInfo containedInfo;
101 containedInfo.containerType = ContainerType::Scalar;
102 containedInfo.declType = vi->type.declType;
103 vi->type.containedTypes.push_back(containedInfo);
105 if ((*iter
)->data
!= "]") {
106 throw CompilerException("Incomplete default size", *(--iter
));
115 int get_precedence(const std::string
&op
) {
117 if (( op
== "<") || ( op
== ">") || (op
== ">=") || (op
== "<=") ||
118 (op
== "==") || (op
== "!=") ) {
120 binPrec
= COMPARE_PREC
;
122 else if (( op
== "+") || ( op
== "-")) {
123 binPrec
= ADD_SUB_PREC
;
125 else if (( op
== "*") || ( op
== "/")) {
126 binPrec
= MULT_DIV_PREC
;
128 else if ( op
== "^") {
129 binPrec
= POWER_PREC
;
131 else if ( op
== "=") {
132 binPrec
= EQUATE_PREC
;
134 else if ( (op
== "!") || (op
== "::") ) {
137 else if ( op
== ".") {
138 binPrec
= SCOPE_PREC
;
140 else if ( op
== ",") {
141 binPrec
= COMMA_GROUP_PREC
;
147 ASTNode
*parse_parens(std::vector
<Token
*>::iterator
&iter
,
148 std::vector
<Token
*>::iterator
&end
) {
152 throw CompilerException("Unclosed parentheses", *(--iter
));
155 returnVal
= parse_expression(iter
, end
);
156 returnVal
->filepos
= (*iter
)->pos
;
157 if ((*iter
)->data
!= ")") {
158 throw CompilerException("Unclosed parentheses", *(--iter
));
168 ASTNode
*parse_array_index(std::vector
<Token
*>::iterator
&iter
,
169 std::vector
<Token
*>::iterator
&end
) {
173 throw CompilerException("Unclosed square brackets", *(--iter
));
176 returnVal
= parse_expression(iter
, end
);
177 returnVal
->filepos
= (*iter
)->pos
;
178 if ((*iter
)->data
!= "]") {
179 throw CompilerException("Unclosed square brackets", *(--iter
));
189 ASTNode
*parse_fun_call(std::vector
<Token
*>::iterator
&iter
,
190 std::vector
<Token
*>::iterator
&end
) {
191 ASTNode
*returnVal
= NULL
;
193 std::vector
<ASTNode
*> args
;
194 std::vector
<ASTNode
*> unwinder
;
196 name
= (*iter
)->data
;
198 if ((iter
== end
) || ((*iter
)->data
!= "(")) {
200 throw CompilerException("Internal integrity error relating to function calls", *iter
);
204 throw CompilerException("Expecting ')' for function call", *iter
);
206 while (((*iter
)->data
!= ")") && (iter
!= end
)) {
207 args
.push_back(parse_expression(iter
, end
));
211 //skip the trailing ')'
215 //what we have is probably a tree of args, but we want a flat list, so fix it
216 if (args
.size() == 1) {
217 BinaryExprAST
*beast
= dynamic_cast<BinaryExprAST
*>(args
[0]);
219 if ((beast
!= NULL
) && (beast
->op
== ",")) {
220 while ((beast
!= NULL
) && (beast
->op
== ",")) {
221 unwinder
.push_back(beast
->children
[1]);
222 LHS
= beast
->children
[0];
223 beast
= dynamic_cast<BinaryExprAST
*>(LHS
);
225 unwinder
.push_back(LHS
);
228 unwinder
.push_back(args
[0]);
232 for (std::vector
<ASTNode
*>::reverse_iterator riter
=unwinder
.rbegin(),
233 rend
=unwinder
.rend(); riter
!= rend
; ++riter
) {
234 args
.push_back(*riter
);
237 returnVal
= new CallExprAST(name
);
238 returnVal
->children
.swap(args
);
240 returnVal
->filepos
= (*iter
)->pos
;
245 ASTNode
*parse_if_block(std::vector
<Token
*>::iterator
&iter
, std::vector
<Token
*>::iterator
&end
) {
246 IfExprAST
*returnVal
= new IfExprAST();
247 returnVal
->filepos
= (*iter
)->pos
;
251 throw CompilerException("Expected if block", *(--iter
));
254 returnVal
->children
.push_back(parse_expression(iter
, end
));
256 BlockAST
*thenBlock
= new BlockAST();
257 while ((iter
!= end
) && ((*iter
)->data
!= "end") && ((*iter
)->data
!= "else")) {
258 thenBlock
->children
.push_back(parse_expression(iter
, end
));
260 returnVal
->children
.push_back(thenBlock
);
263 throw CompilerException("Expected 'end' to end if block", *(--iter
));
266 BlockAST
*elseBlock
= new BlockAST();
267 if ((*iter
)->data
== "else") {
269 while ((iter
!= end
) && ((*iter
)->data
!= "end")) {
270 elseBlock
->children
.push_back(parse_expression(iter
, end
));
273 returnVal
->children
.push_back(elseBlock
);
276 throw CompilerException("Expected 'end' to end if block", *(--iter
));
285 ASTNode
*parse_while_block(std::vector
<Token
*>::iterator
&iter
,
286 std::vector
<Token
*>::iterator
&end
) {
288 WhileExprAST
*returnVal
= new WhileExprAST();
289 returnVal
->filepos
= (*iter
)->pos
;
293 throw CompilerException("Expected while block", *(--iter
));
296 returnVal
->children
.push_back(parse_expression(iter
, end
));
298 BlockAST
*loopBlock
= new BlockAST();
299 while ((iter
!= end
) && ((*iter
)->data
!= "end")) {
300 ASTNode
*ast
= parse_expression(iter
, end
);
301 loopBlock
->children
.push_back(ast
);
303 returnVal
->children
.push_back(loopBlock
);
306 throw CompilerException("Expected 'end' to end while block", *(--iter
));
316 ASTNode
*parse_primary(std::vector
<Token
*>::iterator
&iter
,
317 std::vector
<Token
*>::iterator
&end
) {
318 ASTNode
*returnVal
= NULL
;
319 ASTNode
*index
= NULL
;
323 std::string name
, type
;
325 switch ((*iter
)->tokenType
) {
326 case (TokenType::Num
):
327 val
= atof((*iter
)->data
.c_str());
328 returnVal
= new NumberExprAST(val
);
329 returnVal
->filepos
= (*iter
)->pos
;
332 case (TokenType::String
):
333 returnVal
= new QuoteExprAST((*iter
)->data
);
334 returnVal
->filepos
= (*iter
)->pos
;
337 case (TokenType::Id
):
338 if ((*iter
)->data
== "end") {
339 returnVal
= new EndExprAST();
340 returnVal
->filepos
= (*iter
)->pos
;
342 else if ((*iter
)->data
== "var") {
343 returnVal
= parse_variable_decl(iter
, end
);
345 else if ((*iter
)->data
== "spawn") {
346 returnVal
= parse_variable_decl(iter
, end
);
348 else if ((*iter
)->data
== "new") {
349 returnVal
= parse_variable_decl(iter
, end
);
351 else if ((*iter
)->data
== "if") {
352 returnVal
= parse_if_block(iter
, end
);
354 else if ((*iter
)->data
== "while") {
355 returnVal
= parse_while_block(iter
, end
);
358 else if ((*iter)->data == "receive") {
359 returnVal = parseDataRecvBlock(iter, end);
363 name
= (*iter
)->data
;
367 returnVal
= new VariableExprAST(name
);
368 returnVal
->filepos
= (*iter
)->pos
;
371 if ((*iter
)->data
== "(") {
373 returnVal
= parse_fun_call(iter
, end
);
375 else if ((*iter
)->data
== "[") {
376 index
= parse_array_index(iter
, end
);
377 returnVal
= new ArrayIndexedExprAST(name
, index
);
378 returnVal
->filepos
= (*iter
)->pos
;
381 returnVal
= new VariableExprAST(name
);
382 returnVal
->filepos
= (*iter
)->pos
;
387 case (TokenType::EOL
):
390 case (TokenType::Symbol
):
391 if ((*iter
)->data
== "(") {
392 returnVal
= parse_parens(iter
, end
);
395 else if ((*iter)->data == "@") {
396 returnVal = parsePointcut(iter, end);
400 //std::cout << "Element: " << (*iter)->data << std::endl;
401 throw CompilerException("Unknown symbol", *iter
);
404 case (TokenType::Bool
):
405 if ((*iter
)->data
== "true") {
408 else if ((*iter
)->data
== "false") {
412 throw CompilerException("Unknown boolean value", *iter
);
414 returnVal
= new BooleanExprAST(boolval
);
415 returnVal
->filepos
= (*iter
)->pos
;
420 std::ostringstream msg
;
421 msg
<< "Unknown token type:" << (*iter
)->tokenType
;
422 throw CompilerException(msg
.str(), *iter
);
428 ASTNode
*parse_binary_op(std::vector
<Token
*>::iterator
&iter
,
429 std::vector
<Token
*>::iterator
&end
, int currPrec
, ASTNode
*expr
) {
431 //This uses Chris Lattner's cool precedence parsing trick
432 //For more information see his kaleidoscope tutorial on the llvm website
434 //let's see if what we're sitting on is a math symbol
435 while (iter
!= end
) {
436 std::string op
= (*iter
)->data
;
437 binPrec
= get_precedence(op
);
438 if (binPrec
< currPrec
) {
439 //the next symbol in line is lower precedence than we need
444 //check the precedence of the next hop
445 ASTNode
*rhs
= parse_primary(iter
, end
);
447 throw CompilerException("Incomplete math equation", *iter
);
453 std::string op
= (*iter
)->data
;
454 int nextPrec
= get_precedence(op
);
456 //std::cout << "Outside dive: " << (*iter)->data << " " << binPrec << " " << nextPrec << std::endl;
457 if (binPrec
< nextPrec
) {
459 //std::cout << "Diving in: " << (*iter)->data << std::endl;
460 rhs
= parse_binary_op(iter
, end
, binPrec
+1, rhs
);
463 expr
= new BinaryExprAST(op
, expr
, rhs
);
464 expr
->filepos
= (*iter
)->pos
;
468 throw CompilerException("Incomplete math equation", *(--iter
));
474 ASTNode
*parse_expression(std::vector
<Token
*>::iterator
&iter
, std::vector
<Token
*>::iterator
&end
) {
475 ASTNode
*lhs
= parse_primary(iter
, end
);
477 return parse_binary_op(iter
, end
, 0, lhs
);
483 while (((*iter
)->tokenType
== TokenType::EOL
) && (iter
!= end
)) {
489 PrototypeAST
* parse_prototype(std::vector
<Token
*>::iterator
&iter
,
490 std::vector
<Token
*>::iterator
&end
) {
491 PrototypeAST
* returnVal
= new PrototypeAST();
492 returnVal
->filepos
= (*iter
)->pos
;
494 //parse the return type
495 returnVal
->returnType
= parse_typesig(iter
, end
);
497 if ((*iter
)->data
== "(") {
498 returnVal
->name
= returnVal
->returnType
.declType
;
499 returnVal
->returnType
.declType
= "void";
502 returnVal
->name
= (*iter
)->data
;
505 throw CompilerException("Expected prototype definition", *(--iter
));
509 if ((*iter
)->data
== "(") {
513 throw CompilerException("Incomplete function definition", *iter
);
517 throw CompilerException("Incomplete function definition", *iter
);
520 while (((*iter
)->data
!= ")") && (iter
!= end
)) {
521 returnVal
->children
.push_back(parse_variable_decl(iter
, end
));
522 if ((iter
!= end
) && ((*iter
)->data
== ",")) {
528 //skip the trailing ')'
534 FunctionAST
* parse_function(std::vector
<Token
*>::iterator
&iter
,
535 std::vector
<Token
*>::iterator
&end
) {
537 FunctionAST
* returnVal
= NULL
;
539 if ((iter
!= end
) && ((*iter
)->data
== "extern")) {
542 returnVal
= new FunctionAST();
543 returnVal
->filepos
= (*iter
)->pos
;
544 PrototypeAST
*proto
= parse_prototype(iter
, end
);
546 throw CompilerException("Expecting external function definition", *iter
);
548 proto
->isExtern
= true;
549 returnVal
->children
.push_back(proto
);
550 returnVal
->children
.push_back(new BlockAST()); //add the code empty code block for consistency
553 else if ((iter
!= end
) && ((*iter
)->data
== "def")) {
554 //we may be at a definition
557 returnVal
= new FunctionAST();
558 returnVal
->filepos
= (*iter
)->pos
;
560 PrototypeAST
*proto
= parse_prototype(iter
, end
);
562 throw CompilerException("Expecting function definition", *iter
);
564 proto
->isExtern
= false;
565 returnVal
->children
.push_back(proto
);
567 BlockAST
*bodyBlock
= new BlockAST();
568 ASTNode
*ast
= parse_expression(iter
, end
);
569 while (iter
!= end
) {
571 if (ast
->type() == NodeType::End
) {
576 bodyBlock
->children
.push_back(ast
);
579 ast
= parse_expression(iter
, end
);
581 returnVal
->children
.push_back(bodyBlock
);
588 ActionAST
* parse_action(std::vector
<Token
*>::iterator
&iter
,
589 std::vector
<Token
*>::iterator
&end
) {
591 ActionAST
* returnVal
= NULL
;
593 if ((iter
!= end
) && ((*iter
)->data
== "action")) {
594 //we may be at a definition
597 returnVal
= new ActionAST();
598 returnVal
->filepos
= (*iter
)->pos
;
600 PrototypeAST
*proto
= parse_prototype(iter
, end
);
602 throw CompilerException("Expecting function definition", *iter
);
604 proto
->isExtern
= false;
605 returnVal
->children
.push_back(proto
);
607 BlockAST
*bodyBlock
= new BlockAST();
608 ASTNode
*ast
= parse_expression(iter
, end
);
609 while (iter
!= end
) {
611 if (ast
->type() == NodeType::End
) {
616 bodyBlock
->children
.push_back(ast
);
619 ast
= parse_expression(iter
, end
);
621 returnVal
->children
.push_back(bodyBlock
);
628 ClassAST
* parse_class(std::vector
<Token
*>::iterator
&iter
,
629 std::vector
<Token
*>::iterator
&end
) {
631 ClassAST
*returnVal
= NULL
;
633 if ((iter
!= end
) && ((*iter
)->data
== "class")) {
636 returnVal
= new ClassAST();
637 returnVal
->name
= (*iter
)->data
;
638 returnVal
->filepos
= (*iter
)->pos
;
641 while ((iter
!= end
) && ((*iter
)->data
!= "end")) {
642 if ((*iter
)->data
== "def") {
643 FunctionAST
*fun
= parse_function(iter
, end
);
645 returnVal
->children
.push_back(fun
);
648 else if ((*iter
)->tokenType
== TokenType::Id
) {
649 VarDeclExprAST
*varDecl
= parse_variable_decl(iter
, end
);
650 if (varDecl
!= NULL
) {
651 //FIXME: Check for duplicate definitions
652 returnVal
->children
.push_back(varDecl
);
655 throw CompilerException("Unknown element in class", *(--iter
));
659 //FIXME: Not sure if this is correct
667 throw CompilerException("Expected 'end' at end of class", *(--iter
));
678 ActorAST
* parse_actor(std::vector
<Token
*>::iterator
&iter
,
679 std::vector
<Token
*>::iterator
&end
) {
681 ActorAST
*returnVal
= NULL
;
682 bool isIsolated
= false;
684 if ((iter
!= end
) && ((*iter
)->data
== "isolated")) {
689 if ((iter
!= end
) && ((*iter
)->data
== "actor")) {
692 returnVal
= new ActorAST(isIsolated
);
693 returnVal
->filepos
= (*iter
)->pos
;
694 returnVal
->name
= (*iter
)->data
;
697 while ((iter
!= end
) && ((*iter
)->data
!= "end")) {
698 if ((*iter
)->data
== "def") {
699 FunctionAST
*fun
= parse_function(iter
, end
);
701 returnVal
->children
.push_back(fun
);
704 else if ((*iter
)->data
== "action") {
705 ActionAST
*act
= parse_action(iter
, end
);
707 returnVal
->children
.push_back(act
);
710 else if ((*iter
)->tokenType
== TokenType::Id
){
711 //std::cout << "Var decl enter" << std::endl;
712 VarDeclExprAST
*varDecl
= parse_variable_decl(iter
, end
);
713 //std::cout << "Var decl leave" << std::endl;
714 if (varDecl
!= NULL
) {
715 //FIXME: Check for duplicate definitions
716 returnVal
->children
.push_back(varDecl
);
719 throw CompilerException("Unknown element in class", *(--iter
));
723 //FIXME: Not sure if this is correct
731 throw CompilerException("Expected 'end' at end of class", *(--iter
));
734 ++iter
; //skip over "end"
742 AppAST
* parse(std::vector
<Token
*>::iterator
&iter
,
743 std::vector
<Token
*>::iterator
&end
) {
748 returnVal
= new AppAST();
749 returnVal
->filepos
= (*iter
)->pos
;
751 while (iter
!= end
) {
752 child
= parse_function(iter
, end
);
754 //std::cout << "Pushing function" << std::endl;
755 returnVal
->children
.push_back(child
);
758 child
= parse_class(iter
, end
);
760 //std::cout << "Pushing class" << std::endl;
761 returnVal
->children
.push_back(child
);
764 child
= parse_actor(iter
, end
);
766 //std::cout << "Pushing actor" << std::endl;
767 returnVal
->children
.push_back(child
);
770 child
= parse_action(iter
, end
);
772 //std::cout << "Pushing action" << std::endl;
773 returnVal
->children
.push_back(child
);
777 if ((*iter
)->tokenType
== TokenType::EOL
) {
781 std::ostringstream msg
;
782 msg
<< "Unknown element '" << (*iter
)->data
<< "' of type " << (*iter
)->tokenType
;
783 throw CompilerException(msg
.str(), *iter
);