Грамматика 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;
}
;
%%