Грамматика Pascal + Код

Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску
%{
    Dictionary<string,double> vars = new Dictionary<string,double>();
%}
%union { 
	 public int iVal; 
	 public double dVal; 
         public string sVal; 
         public ExprNode eVal;
         public List<ExprNode> elVal;
         public TreeNode tVal;
         public BlockNode lVal;
         public List<string> lsVal;
	 public GreatType dtVal;
       }
%output=PascalYacc.cs 
%using System.IO
%using Syntax_node_tree
%namespace LexScanner
%start progr

%token kBEGIN kEND kIF kTHEN kELSE kWHILE kDO kVAR
%token ASSIGN SEMICOLUMN LPAREN RPAREN COLUMN COLON POINT  
%token PLUS MINUS MULT DIVIDE 
%token AND OR NOT LT GT EQ NE LE GE DIV MOD
%token <iVal> INTNUM 
%token <dVal> REALNUM 
%token <sVal> STRINGLITERAL
%token <sVal> ID
%token <dtVal> kREAL kINTEGER 

%type <eVal> expr
%type <tVal> operator elsepart
%type <lVal> listoperator progr 
%type <lsVal> ident 
%type <elVal> exprlist 
%type <dtVal> ktype kSimpleType

%left LT GT LE GE EQ NE
%left MINUS PLUS OR
%left MULT DIVIDE AND DIV MOD
%left UMINUS NOT

%%

progr   : {
		$$ = new Program(@$);
	}
	| defss kBEGIN listoperator kEND {
		$$ = $1;
		foreach (Operator oper in $3.list)
			$$.list.Add(oper);
	}
	| error 
	{ 
		System.Console.WriteLine("BAD TEXT!!!");
		break;
	} 
	;

defss : defs {
		$$ = new BlockOperator(@$);
		$$.list.Add($1);
	}
	|defss defs {
		$1.list.Add($2);
		$$ = $1;
	}
	|
	;
	
defs : kVAR ident COLON ktype SEMICOLUMN {
		TipType type;
		if ($4 == "int")
			type = TipType.IntType;
		else if ($4 == "double")
			type = TipType.DoubleType;
		else if ($4 == "bool")
			type = TipType.BoolType;
		else
		{
			// Error: unknown type
		}
		$$ = new VarDef(@$, $2, type);
	}
	;	

ident: ID {
		if (GlobalStructures.isNameExists($1))
		{
			// Error: this name is already used
		}
		Ident Id = new Ident($1, @1);
		listVars.Add(Id);
		$$ = new List<Ident>();
		$$.Add(Id);
	}	
    |ident COLUMN ID {
		if (GlobalStructures.isNameExists($3))
		{
			// Error: this name is already used
		}
		Ident Id = new Ident($3, @3);
		listVars.Add(Id);
		$1.Add(Id);
		$$ = $1;
	}
	;
	
listoperator : operator {
		$$ = new BlockOperator(@$);
		$$.list.Add($1);
	}
	| listoperator SEMICOLUMN operator {
		$1.list.Add($2);
		$$ = $1;
	}
    ;

ktype : kSimpleType
	| error 
	{ 
		System.Console.WriteLine("BAD GREATE TYPE");
		break;
	}
	;

kSimpleType : kREAL {
		$$ = "double";
	} 
	| kINTEGER {
		$$ = "int";
	}
	;

operator: {
		
	}
	| ID ASSIGN expr {
		if (!GlobalStructures.isNameExists($1))
		{
			// Error: Undeclarated identifier
		}
		Ident Id = GlobalStructures.getIdentByName($1);
		$$ = new Assign(Id, $3, @3);
	}
	| kWHILE expr kDO operator {
		if ($2.getType()!=TypType.Boolean)
		{
			// Error: Условие должно иметь логический тип
		}
		$$ = new While($2, $4, @$);
	}
	| kIF expr kTHEN operator elsepart {
		if ($2.getType()!=TypType.Boolean)
		{
			// Error: Условие должно иметь логический тип
		}
		$$=new If($2,$4,$5,@$);
	}
	| kBEGIN listoperator kEND {
		$$ = $2;
	}
        ;

elsepart: {
		$$ = null;
	}
	| kELSE operator {
		$$ = $2;
	}
	;

exprlist : expr {
		// Не понятно, зачем нам нужен список выражений. Реализую, на всякий случай, в виде списка, но класса под это не создавали.
		$$ = new List<Expression>();
		$$.Add($1);
	}
	| exprlist COLUMN expr {
		$1.Add($2);
		$$ = $1;
	}
	;

expr: INTNUM {
		int i = int.Parse($1);
		$$ = new IntConst(i, @1);
	}
    | REALNUM {
		double d = double.Parse($1);
		$$ = new DoubleConst(d, @1);
	}
    | STRINGLITERAL {
		// Нет у нас таких!!!
	}
    | ID {
		if (!GlobalStructures.isNameExists($1))
		{
			// Error: Undeclarated identifier
		}
		$$ = new Ident($1, @1);
	}
    | expr PLUS expr {
		$$ = new BinExpression($1, $3, Op.Plus, @$);
	}
    | expr MINUS expr {
		$$ = new BinExpression($1, $3, Op.Minus, @$);
	}
    | expr MULT expr {
		$$ = new BinExpression($1, $3, Op.Mult, @$);
	}
    | expr DIVIDE expr {
		$$ = new BinExpression($1, $3, Op.Divide, @$);
	}
    | expr DIV expr {
		// Не поддерживается!
	}
    | expr MOD expr {
		// Не поддерживается!
	}
    | expr AND expr {
		if ($1.getType() != TipType.BoolType || $2.getType() != TipType.BoolType)
		{
			// Error: only for bool types
		}
		$$ = new BinExpression($1, $3, Op.And, @$);
	}
    | expr OR expr {
		if ($1.getType() != TipType.BoolType || $2.getType() != TipType.BoolType)
		{
			// Error: only for bool types
		}
		$$ = new BinExpression($1, $3, Op.Or, @$);
	}
    | expr LT expr {
		$$ = new BinExpression($1, $3, Op.Less, @$);
	}
    | expr GT expr {
		$$ = new BinExpression($1, $3, Op.More, @$);
	}
    | expr LE expr {
		$$ = new BinExpression($1, $3, Op.LessEqual, @$);
	}
    | expr GE expr {
		$$ = new BinExpression($1, $3, Op.MoreEqual, @$);		
	}
    | expr EQ expr {
		$$ = new BinExpression($1, $3, Op.Equal, @$);		
	}
    | expr NE expr {
		$$ = new BinExpression($1, $3, Op.NotEqual, @$);		
	}
    | NOT expr {
		if ($2.getType() != TipType.BoolType)
		{
			// Error: type is wrong.
		}
		$$ = new UnarExpression($2, Op.Not, @2);
	}
    | MINUS expr %prec UMINUS {
		if ($2.getType() != TipType.IntType && $2.getType() != TipType.DoubleType)
		{
			// Error: type is wrong.
		}
		$$ = new UnarExpression($2, Op.Minus, @2);
	} 
    | LPAREN expr RPAREN {
		$$ = $2;
	}
	;

%%