308 lines
6.1 KiB
Plaintext
308 lines
6.1 KiB
Plaintext
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include "parser.h"
|
|
using namespace std;
|
|
|
|
#define yyerror(msg) errFunc(msg, &yylloc)
|
|
|
|
int yylex(YYSTYPE *, YYLTYPE *);
|
|
|
|
extern FILE * yyin;
|
|
|
|
void errFunc(const char * str, YYLTYPE * yyllocp);
|
|
|
|
int yywrap()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static YYSTYPE parse_result;
|
|
|
|
%}
|
|
|
|
%pure-parser
|
|
%locations
|
|
%error-verbose
|
|
|
|
/* operators */
|
|
%token ASSIGN;
|
|
%token DASSIGN;
|
|
%token DEQUALS;
|
|
%token DIVIDE;
|
|
%token EQUALS;
|
|
%token GREATER;
|
|
%token LESS;
|
|
%token MATCH;
|
|
%token MINUS;
|
|
%token MOD;
|
|
%token PLUS;
|
|
%token STAR;
|
|
|
|
/* punctuation */
|
|
%token COLON;
|
|
%token COMMA;
|
|
%token DCOLON;
|
|
%token DOLLAR;
|
|
%token DOT;
|
|
%token FROM;
|
|
%token QUESTION;
|
|
%token SEMICOLON;
|
|
|
|
%token LCURLY;
|
|
%token RCURLY;
|
|
%token LBRACKET;
|
|
%token RBRACKET;
|
|
%token LPAREN;
|
|
%token RPAREN;
|
|
|
|
/* literals */
|
|
%token INT_LITERAL;
|
|
%token REAL_LITERAL;
|
|
%token STRING_LITERAL;
|
|
|
|
/* primitive types */
|
|
%token BYTE;
|
|
%token UBYTE;
|
|
%token CHAR;
|
|
%token WCHAR;
|
|
%token SHORT;
|
|
%token USHORT;
|
|
%token INT;
|
|
%token UINT;
|
|
%token LONG;
|
|
%token ULONG;
|
|
%token FLOAT;
|
|
%token DOUBLE;
|
|
|
|
/* keywords */
|
|
%token C;
|
|
%token IMPORT;
|
|
%token MODULE;
|
|
%token RETURN;
|
|
%token STRUCT;
|
|
|
|
/* identifiers */
|
|
%token IDENTIFIER;
|
|
|
|
%%
|
|
|
|
program: program_items {
|
|
$$ = new ProgramNode();
|
|
$$->addChildren($1);
|
|
parse_result = $$;
|
|
}
|
|
;
|
|
|
|
program_items: /* empty */
|
|
| program_item program_items {
|
|
$$ = new ItemsNode();
|
|
$$->addChild($1);
|
|
$$->addChildren($2);
|
|
}
|
|
;
|
|
|
|
program_item: function {
|
|
$$ = $1;
|
|
}
|
|
| c_statement {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
import: IMPORT import_name SEMICOLON
|
|
;
|
|
|
|
import_name: IDENTIFIER import_name_more
|
|
;
|
|
|
|
import_name_more: /* empty */
|
|
| DOT import_name_more_more
|
|
;
|
|
|
|
import_name_more_more: IDENTIFIER import_name_more
|
|
| STAR
|
|
;
|
|
|
|
function: IDENTIFIER LPAREN parameter_list RPAREN COLON type LCURLY function_items RCURLY {
|
|
$$ = new FunctionNode();
|
|
$$->addChild($3);
|
|
$$->addChild($6);
|
|
$$->addChildren($8);
|
|
}
|
|
;
|
|
|
|
function_items: /* empty */
|
|
| statement function_items {
|
|
$$ = new ItemsNode();
|
|
$$->addChild($1);
|
|
$$->addChildren($2);
|
|
}
|
|
;
|
|
|
|
parameter_list: /* empty */
|
|
| variable_spec parameter_list_more {
|
|
$$ = new ItemsNode();
|
|
$$->addChild($1);
|
|
$$->addChildren($2);
|
|
}
|
|
;
|
|
|
|
parameter_list_more: /* empty */
|
|
| COMMA variable_spec parameter_list_more {
|
|
$$ = new ItemsNode();
|
|
$$->addChild($2);
|
|
$$->addChildren($3);
|
|
}
|
|
;
|
|
|
|
primitive_type: BYTE {
|
|
$$ = new PrimitiveTypeNode(BYTE);
|
|
}
|
|
| UBYTE {
|
|
$$ = new PrimitiveTypeNode(UBYTE);
|
|
}
|
|
| CHAR {
|
|
$$ = new PrimitiveTypeNode(CHAR);
|
|
}
|
|
| WCHAR {
|
|
$$ = new PrimitiveTypeNode(WCHAR);
|
|
}
|
|
| SHORT {
|
|
$$ = new PrimitiveTypeNode(SHORT);
|
|
}
|
|
| USHORT {
|
|
$$ = new PrimitiveTypeNode(USHORT);
|
|
}
|
|
| INT {
|
|
$$ = new PrimitiveTypeNode(INT);
|
|
}
|
|
| UINT {
|
|
$$ = new PrimitiveTypeNode(UINT);
|
|
}
|
|
| LONG {
|
|
$$ = new PrimitiveTypeNode(LONG);
|
|
}
|
|
| ULONG {
|
|
$$ = new PrimitiveTypeNode(ULONG);
|
|
}
|
|
;
|
|
|
|
struct_type: STRUCT LCURLY struct_items RCURLY {
|
|
$$ = new StructTypeNode();
|
|
$$->addChildren($3);
|
|
}
|
|
;
|
|
|
|
struct_items: /* empty */
|
|
| struct_item struct_items {
|
|
$$ = new ItemsNode();
|
|
$$->addChild($1);
|
|
$$->addChildren($2);
|
|
}
|
|
;
|
|
|
|
struct_item: variable_declaration {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
variable_declaration: variable_spec SEMICOLON {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
variable_spec: IDENTIFIER COLON type {
|
|
$$ = new VariableSpecNode();
|
|
$$->addChild($1);
|
|
$$->addChild($3);
|
|
}
|
|
;
|
|
|
|
array_type: type LBRACKET RBRACKET {
|
|
$$ = new ArrayTypeNode();
|
|
$$->addChild($1);
|
|
}
|
|
;
|
|
|
|
type: primitive_type {
|
|
$$ = $1;
|
|
}
|
|
| struct_type {
|
|
$$ = $1;
|
|
}
|
|
| array_type {
|
|
$$ = $1;
|
|
}
|
|
| IDENTIFIER {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
statement: expression SEMICOLON {
|
|
$$ = $1;
|
|
}
|
|
| return_statement {
|
|
$$ = $1;
|
|
}
|
|
| c_statement {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
return_statement: RETURN expression SEMICOLON {
|
|
$$ = new ReturnStatementNode();
|
|
$$->addChild($2);
|
|
}
|
|
;
|
|
|
|
expression: assign_expr {
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
assign_expr: lvalue ASSIGN expression {
|
|
$$ = new AssignExprNode();
|
|
$$->addChild($1);
|
|
$$->addChild($3);
|
|
}
|
|
;
|
|
|
|
lvalue: IDENTIFIER {
|
|
$$ = new LValueNode();
|
|
$$->addChild($1);
|
|
}
|
|
;
|
|
|
|
c_statement: C LPAREN STRING_LITERAL RPAREN SEMICOLON {
|
|
$$ = new CStatementNode($3->getString());
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
YYSTYPE parse(const char * fileName)
|
|
{
|
|
yyin = fopen(fileName, "r");
|
|
if (yyin == NULL)
|
|
{
|
|
cerr << "Failed to open file '" << fileName << "'" << endl;
|
|
}
|
|
else if (yyparse())
|
|
{
|
|
cerr << "Aborting." << endl;
|
|
exit(1);
|
|
}
|
|
return parse_result;
|
|
}
|
|
|
|
void errFunc(const char * str, YYLTYPE * yyllocp)
|
|
{
|
|
fprintf(stderr, "error: %s: line %d, column %d\n",
|
|
str,
|
|
yyllocp->first_line,
|
|
yyllocp->first_column);
|
|
}
|