Gittens Web site
 
Font size:      

Dotted grammar for simple expressions

header
{%
#include <ctype.h>
%}

grammar	ExprParser
{

terminals
	PLUS MIN
	MUL  DIV
	NUM
	LP RP
	EOL SEMI

nonterminals
	loop	
	begin
	expr _expr
	term _term
	factor
	syntaxerror


type int
start begin 
error syntaxerror

principles
	.begin: .expr loop	
		;
	.loop :     .EOL
		| .SEMI expr loop  
		;

        expr.loop: . loop {% cout << "\nResult: " << lhsAttr(-1) << endl; %}
		;

	.expr: .term _expr
		;

        term._expr: expr. PLUS term _expr  {% attr(-1) = lhsAttr(-1); %}
                |  expr.MIN term _expr {% attr(-1) = lhsAttr(-1); %}
                |  expr. {% attr(-1) = lhsAttr(-1); %}
		;

        expr PLUS term._expr: term._expr {% attr(-1) = lhsAttr(-3) + lhsAttr(-1); %} ;
        expr MIN term. _expr: term._expr {% attr(-1) = lhsAttr(-3) - lhsAttr(-1); %} ;

	.term: .factor _term
		;

        factor._term: term. MUL factor _term {% attr(-1) = lhsAttr(-1); %}
                | term. DIV factor _term {% attr(-1) = lhsAttr(-1); %}
                | term. {% attr(-1) = lhsAttr(-1); %}
		;

        term MUL factor._term: factor._term {% attr(-1) = lhsAttr(-3) * lhsAttr(-1); %}
		;

        term DIV factor._term: factor._term {% attr(-1) = lhsAttr(-3) / lhsAttr(-1); %}
		;

	.factor: .LP expr RP factor
		| .NUM factor
		;

        LP expr RP. factor: factor. {% attr(-1) = lhsAttr(-2); %}
		;

        NUM. factor : factor. {% attr(-1) = lhsAttr(-1); %}
		;

        . syntaxerror :
                    {% cout << "\nerror : Nonterminal :<" << getSymbolName(lhsToken(-1)) 
                            << "> Lookahead symbol <" << GetSymbolName(lookAhead()) 
                            << ">" << endl; popL(1); 
                    %}
		;

{%
public:

	void parse()
	{
		run();
	}

%}

}

source
{%
        void ExprParser::getToken(Symbol<int> &a)
	{
		char c;

		cin >> c;

		if (isdigit(c))
		{
			a.id = NUM;
			a.attr = c - '0';
			return;
		}

		switch(c)
		{
			case '/' : a.id = DIV; break;
			case '*' : a.id = MUL; break;
			case '+' : a.id = PLUS; break;
			case '-' : a.id = MIN; break;
			case '(' : a.id = LP; break;
			case ')' : a.id = RP; break;
			case ';' : a.id = SEMI; break;
			case '.' : a.id = EOL; break;
			default: a.id = 0;
		}

		a.attr = 0;

	}
%}