summaryrefslogtreecommitdiff
path: root/old/toy/grammar.y
blob: a4499524a371e8759d169fe9311d1866e0c5af08 (plain)
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
%{
	#include <iostream>
	#include <cstdlib>
	#include "node.hpp"

	// AST
	NBlock *programBlock = 0;
	
	extern int grammarlex( );
	extern int grammarget_lineno( void );

	void grammarerror( const char *s )
	{
		std::cerr << "ERROR in line " << grammarget_lineno( ) << ": " << s << std::endl;
		exit( 1 );
	}
%}

%union {
	Node *node;
	NBlock *block;
	NStatement *stmt;
	NExpression *expr;
	NIdentifier *ident;
	NVariableDeclaration *var_decl;
	std::vector<NVariableDeclaration*> *vars;
	std::string *string;
	ExpressionList *exprs;
	int token;
}

%token <string> TIDENTIFIER TINTEGER
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE
%token <token> TCOMMA
%token <token> TEQUAL TMUL TPLUS

%type <block> program stmts block
%type <ident> ident
%type <expr> numeric expr
%type <stmt> stmt func_decl var_decl
%type <vars> func_decl_args
%type <exprs> call_args
%type <token> operator

%left TEQUAL
%left TPLUS
%left TMUL

%start program

%%

program        : stmts                             { programBlock = $1; }
               ;

stmts          : stmt                              { $$ = new NBlock( ); $$->m_statements.push_back( $1 ); }
               | stmts stmt                        { $1->m_statements.push_back( $2 ); }
               ;

stmt           : var_decl                          { }
               | func_decl                         { }
               | expr                              { $$ = new NExpressionStatement( *$1 ); }
               ;

func_decl      : ident ident TLPAREN func_decl_args TRPAREN block
                                                   { $$ = new NFunctionDeclaration( *$1, *$2, *$4, *$6 ); delete $4; }
               ;
                    
func_decl_args : /* procedure */                   { $$ = new VariableList( ); }
               | var_decl                          { $$ = new VariableList( ); $$->push_back( $<var_decl>1 ); }
               | func_decl_args TCOMMA var_decl    { $1->push_back( $<var_decl>3 ); }
               ;

var_decl       : ident ident                       { $$ = new NVariableDeclaration( *$1, *$2 ); }
               | ident ident TEQUAL expr           { $$ = new NVariableDeclaration( *$1, *$2, $4 ); }
               ;

expr           : numeric                           { }
               | ident                             { $<ident>$ = $1; }
               | expr operator expr                { $$ = new NBinaryOperator( *$1, $2, *$3 ); }
               | ident TLPAREN call_args TRPAREN   { $$ = new NFunctionCall( *$1, *$3 ); delete $3; }
               ;

call_args      : /* no params */                   { $$ = new ExpressionList( ); }
               | expr                              { $$ = new ExpressionList( ); $$->push_back( $1 ); }
               | call_args TCOMMA expr             { $1->push_back( $3 ); }
               ;

operator       : TMUL | TPLUS
               ;
                                             
numeric        : TINTEGER                          { $$ = new NInteger( atoi( $1->c_str( ) ) ); delete $1; }
               ;
                                             
block          : TLBRACE /* empty block */ TRBRACE { $$ = new NBlock( ); }
               | TLBRACE stmts TRBRACE             { $$ = $2; }
               ;
                              
ident          : TIDENTIFIER                       { $$ = new NIdentifier( *$1 ); delete $1; }
               ;
                         
%%