Created
April 1, 2012 14:35
-
-
Save RavuAlHemio/2275639 to your computer and use it in GitHub Desktop.
scanner/parser, Lex/Yacc edition
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* vim: set ft=yacc: */ | |
%start ProgramOrEmpty | |
%token TOK_SYM_SEMI | |
%token TOK_SYM_PARBEG | |
%token TOK_SYM_PAREND | |
%token TOK_SYM_COMMA | |
%token TOK_SYM_EQUALS | |
%token TOK_SYM_TILDE | |
%token TOK_SYM_ARROW | |
%token TOK_SYM_MINUS | |
%token TOK_SYM_PLUS | |
%token TOK_SYM_ASTER | |
%token TOK_SYM_DOT | |
%token TOK_SYM_GT | |
%token TOK_SYM_USCORE | |
%token TOK_KEY_COND | |
%token TOK_KEY_END | |
%token TOK_KEY_NOT | |
%token TOK_KEY_OR | |
%token TOK_NUMBER | |
%token TOK_IDENT | |
%{ | |
#include "common.h" | |
#include "astmake.h" | |
extern ast_generic_node *ast_root; | |
%} | |
%union { | |
char *sval; | |
numeric_type numval; | |
ast_generic_node *n; | |
struct | |
{ | |
size_t argcount; | |
char **argnames; | |
} argnames; | |
struct | |
{ | |
size_t argcount; | |
ast_generic_node **argexprs; | |
} args; | |
struct | |
{ | |
size_t casecount; | |
ast_generic_node **cases; | |
} cases; | |
} | |
/*@attributes { ast_generic_node *n; } Program Funcdef Expr Term MinusNotSeries PlusSeries AsterSeries OrSeries DotSeries CondContentExpr Lexpr Lterm | |
@attributes { char *name; } TOK_IDENT | |
@attributes { numeric_type val; } TOK_NUMBER | |
@attributes { size_t argcount; char **argnames; } ParamNames | |
@attributes { size_t argcount; ast_generic_node **argexprs; } Params | |
@attributes { size_t casecount; ast_generic_node **cases; } CondExprSeries;*/ | |
%% | |
ProgramOrEmpty | |
: Program | |
| | |
; | |
Program | |
: Program Funcdef TOK_SYM_SEMI | |
{ | |
ast_root = $<n>$ = ast_make_program_expand( | |
$<n>1, | |
$<n>2 | |
); | |
} | |
| Funcdef TOK_SYM_SEMI | |
{ | |
ast_root = $<n>$ = ast_make_program($<n>1); | |
} | |
; | |
Funcdef | |
: TOK_IDENT /* Funktionsname */ | |
TOK_SYM_PARBEG ParamNames TOK_SYM_PAREND /* Parameter */ | |
TOK_SYM_EQUALS Expr /* Definition */ | |
{ | |
$<n>$ = ast_make_funcdef( | |
$<sval>1, | |
$<argnames>3.argcount, | |
$<argnames>3.argnames, | |
$<n>6 | |
); | |
free($<sval>1); | |
} | |
| TOK_IDENT | |
TOK_SYM_PARBEG TOK_SYM_PAREND /* parameterlos */ | |
TOK_SYM_EQUALS Expr | |
{ | |
$<n>$ = ast_make_funcdef( | |
$<sval>1, | |
0, NULL, | |
$<n>5 | |
); | |
free($<sval>1); | |
} | |
; | |
ParamNames | |
: ParamNames TOK_SYM_COMMA TOK_IDENT | |
{ | |
$<argnames>$.argcount = $<argnames>1.argcount + 1; | |
$<argnames>$.argnames = ast_make_argnames_expand( | |
$<argnames>1.argcount, | |
$<argnames>1.argnames, | |
$<sval>3 | |
); | |
free($<sval>3); | |
} | |
| TOK_IDENT | |
{ | |
$<argnames>$.argcount = 1; | |
$<argnames>$.argnames = ast_make_argnames($<sval>1); | |
free($<sval>1); | |
} | |
; | |
Expr | |
: TOK_KEY_COND CondExprSeries TOK_SYM_ARROW Expr TOK_KEY_END | |
{ | |
$<n>$ = ast_make_cond( | |
$<cases>2.casecount, | |
$<cases>2.cases, | |
$<n>4 | |
); | |
} | |
| TOK_KEY_COND TOK_SYM_ARROW Expr TOK_KEY_END | |
{ | |
/* | |
Don't bother making a conditional construction here. | |
Just pass the expression upwards. | |
*/ | |
$<n>$ = $<n>3; | |
} | |
| Term | |
{ | |
$<n>$ = $<n>1; | |
} | |
| MinusNotSeries | |
{ | |
$<n>$ = $<n>1; | |
} | |
| PlusSeries | |
{ | |
$<n>$ = $<n>1; | |
} | |
| AsterSeries | |
{ | |
$<n>$ = $<n>1; | |
} | |
| OrSeries | |
{ | |
$<n>$ = $<n>1; | |
} | |
| DotSeries | |
{ | |
$<n>$ = $<n>1; | |
} | |
| Term TOK_SYM_GT Term | |
{ | |
$<n>$ = ast_make_binop(AST_OP_GT, $<n>1, $<n>3); | |
} | |
| Term TOK_SYM_EQUALS Term | |
{ | |
$<n>$ = ast_make_binop(AST_OP_EQUAL, $<n>1, $<n>3); | |
} | |
; | |
Term | |
: TOK_SYM_PARBEG Expr TOK_SYM_PAREND | |
{ | |
$<n>$ = $<n>2; | |
} | |
| TOK_NUMBER | |
{ | |
$<n>$ = ast_make_number($<numval>1); | |
} | |
| TOK_IDENT TOK_SYM_PARBEG TOK_SYM_PAREND | |
{ | |
$<n>$ = ast_make_funccall( | |
$<sval>1, | |
0, NULL | |
); | |
free($<sval>1); | |
} | |
| TOK_IDENT TOK_SYM_PARBEG Params TOK_SYM_PAREND | |
{ | |
$<n>$ = ast_make_funccall( | |
$<sval>1, | |
$<args>3.argcount, $<args>3.argexprs | |
); | |
free($<sval>1); | |
} | |
| TOK_IDENT | |
{ | |
$<n>$ = ast_make_varacc($<sval>1); | |
free($<sval>1); | |
} | |
; | |
Params | |
: Params TOK_SYM_COMMA Expr | |
{ | |
$<args>$.argcount = $<args>1.argcount + 1; | |
$<args>$.argexprs = ast_make_argexprs_expand( | |
$<args>1.argcount, | |
$<args>1.argexprs, | |
$<n>3 | |
); | |
} | |
| Expr | |
{ | |
$<args>$.argcount = 0; | |
$<args>$.argexprs = ast_make_argexprs($<n>1); | |
} | |
; | |
MinusNotSeries | |
: TOK_SYM_MINUS MinusNotSeries | |
{ | |
$<n>$ = ast_make_unop( | |
AST_OP_MINUS, $<n>2 | |
); | |
} | |
| TOK_KEY_NOT MinusNotSeries | |
{ | |
$<n>$ = ast_make_unop( | |
AST_OP_NOT, $<n>2 | |
); | |
} | |
| TOK_SYM_MINUS Term | |
{ | |
$<n>$ = ast_make_unop( | |
AST_OP_MINUS, $<n>2 | |
); | |
} | |
| TOK_KEY_NOT Term | |
{ | |
$<n>$ = ast_make_unop( | |
AST_OP_NOT, $<n>2 | |
); | |
} | |
; | |
PlusSeries | |
: PlusSeries TOK_SYM_PLUS Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_ADD, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
| Term TOK_SYM_PLUS Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_ADD, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
; | |
AsterSeries | |
: AsterSeries TOK_SYM_ASTER Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_MUL, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
| Term TOK_SYM_ASTER Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_MUL, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
; | |
OrSeries | |
: OrSeries TOK_KEY_OR Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_MUL, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
| Term TOK_KEY_OR Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_MUL, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
; | |
DotSeries | |
/* left-recursion: left-assoc | |
: DotSeries TOK_SYM_DOT Term | |
@{ | |
@i @DotSeries.0.n@ = ast_make_binop( | |
AST_OP_CONS, | |
@DotSeries.1.n@, | |
@Term.n@ | |
); | |
@}*/ | |
/* right-recursion: right-assoc */ | |
: Term TOK_SYM_DOT DotSeries | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_CONS, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
| Term TOK_SYM_DOT Term | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_CONS, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
; | |
CondExprSeries | |
: CondExprSeries CondContentExpr | |
{ | |
$<cases>$.casecount = | |
$<cases>1.casecount + 1 | |
; | |
$<cases>$.cases = ast_make_condcasearr_expand( | |
$<cases>1.casecount, | |
$<cases>1.cases, | |
$<n>2 | |
); | |
} | |
| CondContentExpr | |
{ | |
$<cases>$.casecount = 1; | |
$<cases>$.cases = ast_make_condcasearr( | |
$<n>1 | |
); | |
} | |
; | |
CondContentExpr | |
: Expr TOK_SYM_TILDE Lexpr TOK_SYM_ARROW Expr TOK_SYM_SEMI | |
{ | |
$<n>$ = ast_make_condstruc( | |
$<n>1, | |
$<n>3, | |
$<n>5 | |
); | |
} | |
| Expr TOK_SYM_ARROW Expr TOK_SYM_SEMI | |
{ | |
$<n>$ = ast_make_condcase( | |
$<n>1, | |
$<n>3 | |
); | |
} | |
; | |
Lexpr | |
/* left-recursion = left-associativity | |
: Lexpr TOK_SYM_DOT Lterm | |
@{ | |
@i @Lexpr.0.n@ = ast_make_binop( | |
AST_OP_CONS, | |
@Lexpr.1.n@, | |
@Lterm.n@ | |
); | |
@}*/ | |
/* right-recursion = right-associativity */ | |
: Lterm TOK_SYM_DOT Lexpr | |
{ | |
$<n>$ = ast_make_binop( | |
AST_OP_CONS, | |
$<n>1, | |
$<n>3 | |
); | |
} | |
| Lterm | |
{ | |
$<n>$ = $<n>1; | |
} | |
; | |
Lterm | |
: TOK_SYM_PARBEG Lexpr TOK_SYM_PAREND | |
{ | |
$<n>$ = $<n>1; | |
} | |
| TOK_IDENT /* Variablendefinition */ | |
{ | |
$<n>$ = ast_make_strucvardef( | |
$<sval>1 | |
); | |
free($<sval>1); | |
} | |
| TOK_SYM_USCORE | |
{ | |
$<n>$ = ast_make_consumer(); | |
} | |
; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* vim: set ft=lex: */ | |
%option noyywrap | |
%{ | |
#include "common.h" | |
#include "astmake.h" | |
#include "parser.h" | |
#ifdef __GNUC__ | |
static void yyunput(int c, register char * yy_bp) __attribute__((unused)); | |
static int input(void) __attribute__((unused)); | |
#endif | |
%} | |
LCASE [a-z] | |
UCASE [A-Z] | |
DIGIT [0-9] | |
HEXDIGIT [0-9A-Fa-f] | |
ALPHANUM [a-zA-Z0-9] | |
IDFIRST [a-zA-Z] | |
IDREST [a-zA-Z0-9] | |
%% | |
";" return TOK_SYM_SEMI; | |
"(" return TOK_SYM_PARBEG; | |
")" return TOK_SYM_PAREND; | |
"," return TOK_SYM_COMMA; | |
"=" return TOK_SYM_EQUALS; | |
"~" return TOK_SYM_TILDE; | |
"->" return TOK_SYM_ARROW; | |
"-" return TOK_SYM_MINUS; | |
"+" return TOK_SYM_PLUS; | |
"*" return TOK_SYM_ASTER; | |
"." return TOK_SYM_DOT; | |
">" return TOK_SYM_GT; | |
"_" return TOK_SYM_USCORE; | |
"cond" return TOK_KEY_COND; | |
"end" return TOK_KEY_END; | |
"not" return TOK_KEY_NOT; | |
"or" return TOK_KEY_OR; | |
{DIGIT}+ yylval.numval = lex_dectoint(yytext); return TOK_NUMBER; | |
{DIGIT}{HEXDIGIT}*"H" yylval.numval = lex_hextoint(yytext); return TOK_NUMBER; | |
{IDFIRST}{IDREST}* yylval.sval = strdup(yytext); return TOK_IDENT; | |
"//".* ; | |
[ \t\n\r]+ ; | |
. lexerrorv("illegal tokens: '%s'", yytext); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment