Грамматика языка Pascal: различия между версиями
Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску
AlexHit (обсуждение | вклад) Нет описания правки |
AlexHit (обсуждение | вклад) Нет описания правки |
||
(не показана 1 промежуточная версия этого же участника) | |||
Строка 1: | Строка 1: | ||
--[[Участник:AlexHit|Венцко Александр Зиновьевич]] 21:11, 21 сентября 2011 (UTC) | --[[Участник:AlexHit|Венцко Александр Зиновьевич]] 21:11, 21 сентября 2011 (UTC) | ||
'''Грамматика''' | '''Грамматика''' | ||
Строка 12: | Строка 6: | ||
Dictionary<string,double> vars = new Dictionary<string,double>(); | Dictionary<string,double> vars = new Dictionary<string,double>(); | ||
%} | %} | ||
%output=Yacc.cs | |||
%union { | %union { | ||
public int iVal; | public int iVal; | ||
Строка 17: | Строка 14: | ||
public string sVal; | public string sVal; | ||
public ExprNode eVal; | public ExprNode eVal; | ||
public TreeNode tVal; | public TreeNode tVal; | ||
public BlockNode lVal; | public BlockNode lVal; | ||
Строка 23: | Строка 19: | ||
public GreatType dtVal; | public GreatType dtVal; | ||
} | } | ||
%using System.IO | %using System.IO | ||
%using Syntax_node_tree | %using Syntax_node_tree | ||
%namespace LexScanner | %namespace LexScanner | ||
%start progr | %start progr | ||
%token kBEGIN kEND kIF kTHEN kELSE kWHILE kDO kVAR | %token kBEGIN kEND kIF kTHEN kELSE kWHILE kDO kVAR kWRITE kWRITELN | ||
%token ASSIGN SEMICOLUMN LPAREN RPAREN COLUMN COLON POINT | %token ASSIGN SEMICOLUMN LPAREN RPAREN COLUMN COLON POINT | ||
%token PLUS MINUS MULT DIVIDE | %token PLUS MINUS MULT DIVIDE | ||
Строка 37: | Строка 34: | ||
%token <sVal> STRINGLITERAL | %token <sVal> STRINGLITERAL | ||
%token <sVal> ID | %token <sVal> ID | ||
%token <dtVal> kREAL kINTEGER | %token <dtVal> kREAL kINTEGER kBOOLEAN | ||
%type <eVal> expr | %type <eVal> expr | ||
Строка 43: | Строка 40: | ||
%type <lVal> listoperator progr | %type <lVal> listoperator progr | ||
%type <lsVal> ident | %type <lsVal> ident | ||
%type <dtVal> ktype kSimpleType | %type <dtVal> ktype kSimpleType | ||
Строка 53: | Строка 49: | ||
%% | %% | ||
progr : {} | progr : | ||
| defss kBEGIN listoperator kEND {} | { | ||
$$ = new Program(@$); | |||
} | |||
| defss kBEGIN listoperator kEND | |||
{ | |||
$$ = $1; | |||
foreach (Operator oper in $3.list) | |||
$$.list.Add(oper); | |||
} | |||
| error | | error | ||
{ | { | ||
Строка 63: | Строка 67: | ||
defss : defs | defss : defs | ||
|defss defs | { | ||
$$ = new BlockOperator(@$); | |||
$$.list.Add($1); | |||
} | |||
|defss defs { | |||
$1.list.Add($2); | |||
$$ = $1; | |||
} | |||
| | | | ||
; | ; | ||
defs : kVAR ident COLON ktype SEMICOLUMN {} | 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 | 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 | ktype : kSimpleType | ||
Строка 86: | Строка 138: | ||
; | ; | ||
kSimpleType : kREAL {} | kSimpleType : kREAL | ||
| kINTEGER {} | { | ||
$$ = "double"; | |||
} | |||
| kINTEGER | |||
{ | |||
$$ = "int"; | |||
} | |||
| kBOOLEAN | |||
{ | |||
$$ = "bool" | |||
} | |||
; | ; | ||
operator: {} | operator: {} | ||
| ID ASSIGN expr {} | | ID ASSIGN expr | ||
| kWHILE expr kDO operator {} | { | ||
if (!GlobalStructures.isNameExists($1)) | |||
| kIF expr kTHEN operator elsepart {} | { | ||
| kBEGIN listoperator kEND {} | // 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; | |||
} | |||
| kWRITE LPAREN expr RPAREN | |||
{ | |||
System.Console.Write($3); | |||
} | |||
| kWRITELN LPAREN expr RPAREN | |||
{ | |||
System.Console.WriteLine($3); | |||
} | |||
; | ; | ||
elsepart: {} | elsepart: | ||
| kELSE operator {} | { | ||
$$ = null; | |||
} | |||
| kELSE operator { | |||
$$ = $2; | |||
} | |||
; | ; | ||
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; | |||
} | |||
; | ; | ||
Строка 217: | Строка 397: | ||
keywords.Add("real",(int)Tokens.kREAL); | keywords.Add("real",(int)Tokens.kREAL); | ||
keywords.Add("integer",(int)Tokens.kINTEGER); | keywords.Add("integer",(int)Tokens.kINTEGER); | ||
keywords.Add("boolean",(int)Tokens.kBOOLEAN); | |||
keywords.Add("begin",(int)Tokens.kBEGIN); | keywords.Add("begin",(int)Tokens.kBEGIN); | ||
keywords.Add("end",(int)Tokens.kEND); | keywords.Add("end",(int)Tokens.kEND); | ||
Строка 224: | Строка 405: | ||
keywords.Add("do",(int)Tokens.kDO); | keywords.Add("do",(int)Tokens.kDO); | ||
keywords.Add("while",(int)Tokens.kWHILE); | keywords.Add("while",(int)Tokens.kWHILE); | ||
keywords.Add("write",(int)Tokens.kWRITE); | |||
keywords.Add("writeln",(int)Tokens.kWRITELN); | |||
keywords.Add("div",(int)Tokens.DIV); | keywords.Add("div",(int)Tokens.DIV); | ||
keywords.Add("mod",(int)Tokens.MOD); | keywords.Add("mod",(int)Tokens.MOD); |
Текущая версия от 21:40, 5 октября 2011
--Венцко Александр Зиновьевич 21:11, 21 сентября 2011 (UTC)
Грамматика
%{ Dictionary<string,double> vars = new Dictionary<string,double>(); %} %output=Yacc.cs %union { public int iVal; public double dVal; public string sVal; public ExprNode eVal; public TreeNode tVal; public BlockNode lVal; public List<string> lsVal; public GreatType dtVal; } %using System.IO %using Syntax_node_tree %namespace LexScanner %start progr %token kBEGIN kEND kIF kTHEN kELSE kWHILE kDO kVAR kWRITE kWRITELN %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 kBOOLEAN %type <eVal> expr %type <tVal> operator elsepart %type <lVal> listoperator progr %type <lsVal> ident %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"; } | kBOOLEAN { $$ = "bool" } ; 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; } | kWRITE LPAREN expr RPAREN { System.Console.Write($3); } | kWRITELN LPAREN expr RPAREN { System.Console.WriteLine($3); } ; elsepart: { $$ = null; } | kELSE operator { $$ = $2; } ; 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; } ; %%
Сканер
%namespace LexScanner %using Syntax_node_tree; Alpha [a-zA-Z_] INTNUM [0-9]+ REALNUM {INTNUM}\.{INTNUM} ID [a-zA-Z_][a-zA-Z0-9_]* %x COMMENT %x COMMENT1 %% "{" { BEGIN(COMMENT);} <COMMENT> "}" { BEGIN(INITIAL);} <COMMENT> <<EOF>> { Console.WriteLine("Комментарий не закрыт");} "(*" { BEGIN(COMMENT1);} <COMMENT1> "*)" { BEGIN(INITIAL);} <COMMENT1> <<EOF>> { Console.WriteLine("Комментарий не закрыт");} ":=" { return (int)Tokens.ASSIGN; } ";" { return (int)Tokens.SEMICOLUMN; } "-" { return (int)Tokens.MINUS; } "+" { return (int)Tokens.PLUS; } "*" { return (int)Tokens.MULT; } "/" { return (int)Tokens.DIVIDE; } "<" { return (int)Tokens.LT; } ">" { return (int)Tokens.GT; } "<=" { return (int)Tokens.LE; } ">=" { return (int)Tokens.GE; } "=" { return (int)Tokens.EQ; } "<>" { return (int)Tokens.NE; } "(" { return (int)Tokens.LPAREN; } ")" { return (int)Tokens.RPAREN; } "," { return (int)Tokens.COLUMN; } ":" { return (int)Tokens.COLON; } "." { return (int)Tokens.POINT; } \'[^']*\' { yylval.sVal = yytext.Substring(1,yytext.Length-2); return (int)Tokens.STRINGLITERAL; } {ID} { int res = ScannerHelper.GetIDToken(yytext); string s = yytext.ToLower(); if (s=="integer") yylval.dtVal.DType=DataType.INTTYPE; if (s == "real") yylval.dtVal.DType =DataType.DOUBLETYPE; if (res == (int)Tokens.ID) yylval.sVal = yytext; return res; } {INTNUM} { yylval.iVal = int.Parse(yytext); return (int)Tokens.INTNUM; } {REALNUM} { yylval.dVal = double.Parse(yytext,new System.Globalization.CultureInfo("en-US")); return (int)Tokens.REALNUM; } %{ yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol); %} %% class ScannerHelper { private static Dictionary<string,int> keywords; static ScannerHelper() { keywords = new Dictionary<string,int>(); keywords.Add("var",(int)Tokens.kVAR); keywords.Add("real",(int)Tokens.kREAL); keywords.Add("integer",(int)Tokens.kINTEGER); keywords.Add("boolean",(int)Tokens.kBOOLEAN); keywords.Add("begin",(int)Tokens.kBEGIN); keywords.Add("end",(int)Tokens.kEND); keywords.Add("if",(int)Tokens.kIF); keywords.Add("then",(int)Tokens.kTHEN); keywords.Add("else",(int)Tokens.kELSE); keywords.Add("do",(int)Tokens.kDO); keywords.Add("while",(int)Tokens.kWHILE); keywords.Add("write",(int)Tokens.kWRITE); keywords.Add("writeln",(int)Tokens.kWRITELN); keywords.Add("div",(int)Tokens.DIV); keywords.Add("mod",(int)Tokens.MOD); keywords.Add("and",(int)Tokens.AND); keywords.Add("or",(int)Tokens.OR); keywords.Add("not",(int)Tokens.NOT); } public static int GetIDToken(string s) { s = s.ToLower(); if (keywords.ContainsKey(s)) { return keywords[s]; } else return (int)Tokens.ID; } }