📄 parser.y
字号:
%{///////////////////////////////////////////////////////////////////////////////// $Header: $//-----------------------------------------------------------------------------// Project: ShortHand interpreter// Author: Andrei Remenchuk <andrei@remenchuk.com>//-----------------------------------------------------------------------------// parsery.y: ShortHand grammar///////////////////////////////////////////////////////////////////////////////#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#ifdef WIN32#include <windows.h>#endif#include "shorthand.h"#include "yydef.h"#include "module.h"#include "nodes.h"//// parser_module is a pointer to the ShhModule object passed as parameter// to yyparse() function//#define MODULE ((ShhModule*)parser_module)// we redefined yylex() as module's method instead of stanalone function#define yylex MODULE->module_yylex#define yyerror MODULE->module_yyerror// this defines lexer object#define LEXER MODULE->m_lexer// macros for constructing AST nodes#define NEW0(T) (T*) MODULE->include(new T())#define NEW(T,arg1) (T*) MODULE->include(new T(arg1))#define NEW2(T,arg1,arg2) (T*) MODULE->include(new T(arg1,arg2))#define NEW3(T,arg1,arg2,arg3) (T*) MODULE->include(new T(arg1,arg2,arg3))#define NEW4(T,arg1,arg2,arg3,arg4) (T*) MODULE->include(new T(arg1,arg2,arg3,arg4))%}%pure_parser%token_table%union { int num; double fnum; const char* str; ShhVariable* var; ShhExecutable* exec; ShhExpression* exp; ShhPredicate* pred; ShhBatch* batch; ShhQualifier* qualifier; ShhExpressionList* explist; ShhFunctionCall* call; ShhParameterList* params;
};%token LEX_ERROR%token FOO%token <str> BARE_HTML%token <str> BARE_HTML_EOF%token <str> HTML_AND_PRINT%token <str> IDENT OBJECT_IDENT%token <num> NUMBER%token <fnum> _FLOAT%token <str> STRING%token IF THEN ELSE ALL END PRINT PRINTLN%token GRID WHILE BREAK CONTINUE FOR TO%token K_RETURN FUNCTION K_NULL%token INCLUDE JUMP LOCAL
%token AS FOREACH%token MIN MAX %type <exp> expression %type <exec> statement super_statement subst%type <batch> statements content locals%type <exec> loop%type <exec> if_block else_block%type <exec> local%type <pred> condition%type <explist> arguments arglist%type <call> call%type <params> paramlist params%nonassoc LOWER_THAN_ELSE%nonassoc ELSE%nonassoc ELSEIF%nonassoc EQL
%left OR%left AND%nonassoc EQ NE LE GE '<' '>'%right NOT UNOT %nonassoc '=' COMPARE%nonassoc HIGHER_THAN_EXPRESSION%left '&'%left '+' '-'%nonassoc '%'%left '*' '/'%right '!' UMINUS%left '.'%nonassoc K_NEW
%left '[' ']' '{' '}'
%left '('%%input : content { const char* html = LEXER->flush_html(); if (html != NULL && *html != '\0') while(*html && strchr(" \t\r\n", *html) != 0) html++; if (html != NULL && *html != '\0') { if (yydebug) printf("input: OOB html found\n"); TRACE((5, "input(%s): OOB html found (%d characters):\n---oob start---\n%s\n--oob end-----\n", MODULE->getName(), strlen(html), html)); ShhBatch* batch = NEW(ShhBatch, $1); batch->add( NEW(ShhHTML, html) ); MODULE->setEntry(batch); } else { MODULE->setEntry($1); } if (yydebug) printf("got input\n"); TRACE((5, "input is block of stamements\n")); } ;content : /* empty */ { $$ = NEW0(ShhBatch); } | statements { $$ = $1; } ;subst : newlines { $$ = NEW0(ShhNOP); } | statement { $$ = $1; } | super_statement { $$ = $1; }
| ';'
{ $$ = NEW0(ShhNOP); }
;statements : subst { $$ = NEW(ShhBatch,$1); } | statements subst { $$ = $1; $$->add($2); } ;super_statement : BARE_HTML { $$ = NEW(ShhHTML,$1); } | HTML_AND_PRINT expression { ShhBatch* batch = NEW(ShhBatch, NEW(ShhHTML,$1)); batch->add(NEW(ShhPrint,$2)); $$ = batch; } ;statement : if_block { $$ = $1; } | loop { $$ = $1; } | BREAK { $$ = NEW0(ShhBreak); } | CONTINUE { $$ = NEW0(ShhContinue); } | expression '=' expression { $$ = NEW2(ShhAssignment, $1, $3); } /*| IDENT '.' IDENT { $$ = NEW3(ShhVoidMethodCall, $1, $3, NULL); }*/ | expression '.' IDENT '(' arguments ')' { $$ = NEW3(ShhVoidMethodCall, $1, $3, $5); }
| PRINT expression { $$ = NEW(ShhPrint, $2); } | PRINTLN expression { $$ = NEW2(ShhPrint, $2, true); } | INCLUDE expression { $$ = NEW(ShhInclude, $2); } | JUMP expression { $$ = NEW(ShhJump, $2); } | call { $$ = NEW(ShhVoid, $1); } | FUNCTION IDENT '(' params ')' statements END FUNCTION { $$ = NEW3(ShhDefun, $2, $4, $6); } | K_RETURN expression { $$ = NEW(ShhReturn, $2); } | K_RETURN { $$ = NEW(ShhReturn, NEW(ShhConstant, "")); } | LOCAL locals { $$ = $2; } ;
newlines : '\n' | newlines '\n' ;local : IDENT { $$ = NEW(ShhLocalDecl, $1); }
| IDENT '=' expression { $$ = NEW2(ShhLocalDecl, $1, $3); } ;locals : local { $$ = NEW(ShhBatch, $1); } | locals ',' local { $$ = $1; $$->add($3); } ;call : IDENT '(' arguments ')' { $$ = NEW2(ShhFunctionCall, $1, $3); } ;loop : GRID '(' IDENT ')' statements END GRID { $$ = NEW2(ShhGrid, $3, $5); } | GRID '(' IDENT ',' expression ')' statements END GRID { $$ = NEW3(ShhGrid, $3, $7, $5); } | GRID '(' IDENT ',' expression ',' expression ')' statements END GRID { $$ = NEW4(ShhGrid, $3, $9, $5, $7); } | WHILE condition statements END WHILE { $$ = NEW2(ShhWhileLoop, $2, $3); } | FOR IDENT '=' expression TO expression statements END FOR { $$ = NEW4(ShhForLoop, $2, $4, $6, $7); }
| FOREACH expression AS expression statements END FOR
{ $$ = NEW4(ShhForeachLoop, $2, NULL, $4, $5); }
| FOREACH expression AS expression EQL expression statements END FOR
{ $$ = NEW4(ShhForeachLoop, $2, $4, $6, $7); }
;arguments : /* empty */ { $$ = ShhExpressionList::null; } | arglist { $$ = $1; } ; paramlist : IDENT { $$ = NEW0(ShhParameterList); $$->add(new ShhParameter($1)); } | paramlist ',' IDENT { $$ = $1; $$->add(new ShhParameter($3)); } ;params : /* empty */ { $$ = NEW0(ShhParameterList); } | paramlist { $$ = $1; } ;arglist : expression { $$ = NEW(ShhExpressionList, $1); } | arglist ',' expression { $$ = $1; $1->add($3); } ;expression : NUMBER { $$ = NEW(ShhConstant, $1); } | _FLOAT { $$ = NEW(ShhConstant, $1); } | K_NULL { $$ = NEW(ShhConstant, ShhValue::null()); } | STRING { $$ = NEW(ShhConstant, $1); } | IDENT '(' arguments ')' { $$ = NEW2(ShhFunctionCall, $1, $3); } | IDENT { $$ = NEW(ShhVariableRef, $1); } | expression '.' IDENT { $$ = NEW2(ShhPropertyRef, $1, $3 ); } | expression '.' IDENT '(' arguments ')' %prec UMINUS { $$ = NEW3(ShhValueMethodCall, $1, $3, $5); } | '(' expression ')' { $$ = $2; } | expression '+' expression { $$ = NEW3(ShhArithmetic, '+', $1, $3); } | expression '-' expression { $$ = NEW3(ShhArithmetic, '-', $1, $3); } | expression '*' expression { $$ = NEW3(ShhArithmetic, '*', $1, $3); } | expression '/' expression { $$ = NEW3(ShhArithmetic, '/', $1, $3); } | expression '%' expression { $$ = NEW3(ShhArithmetic, '%', $1, $3); } | '-' expression %prec UMINUS { $$ = NEW3(ShhArithmetic, '-', NEW(ShhConstant, 0), $2); } | expression '&' expression { $$ = NEW2(ShhConcat, $1, $3); } | K_NEW OBJECT_IDENT { $$ = NEW2(ShhObjectCtor, $2, NULL); } | K_NEW call { $$ = NEW2(ShhObjectCtor, $2->name(), $2->args()); }
| expression '[' expression ']'
{ $$ = NEW2(ShhArrayElement, $1, $3); }
| expression '{' expression '}'
{ $$ = NEW2(ShhHashElement, $1, $3); }
;condition : expression '<' expression { $$ = NEW3(ShhComparison, '<', $1, $3); }
| expression '>' expression { $$ = NEW3(ShhComparison, '>', $1, $3); }
| expression '=' expression { $$ = NEW3(ShhComparison, '=', $1, $3); }
| expression LE expression { $$ = NEW3(ShhComparison, LE, $1, $3); }
| expression GE expression { $$ = NEW3(ShhComparison, GE, $1, $3); }
| expression NE expression { $$ = NEW3(ShhComparison, NE, $1, $3); }
| '(' condition ')' { $$ = $2; }
| condition AND condition { $$ = NEW3(ShhBooleanArithmetic, AND, $1, $3); }
| condition OR condition { $$ = NEW3(ShhBooleanArithmetic, OR, $1, $3); }
| NOT condition { $$ = NEW3(ShhBooleanArithmetic, NOT, $2, NULL); }
| expression { $$ = NEW3(ShhComparison, NE, NEW(ShhConstant, 0), $1); } ;if_block : IF condition THEN statements else_block { $$ = NEW3(ShhConditionBlock, $2, $4, $5); } | IF condition THEN else_block { $$ = NEW3(ShhConditionBlock, $2, NULL, $4); } ;else_block : END IF { $$ = NEW0(ShhNOP); } | ELSE statements END IF { $$ = $2; } | ELSEIF condition THEN statements else_block { $$ = NEW3(ShhConditionBlock, $2, $4, $5); } ;%%
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -