Correct error handling using patched LIME parse_engine

databind
vitalif 2013-04-20 11:05:45 +00:00 committed by Vitaliy Filippov
parent dbd171834b
commit cccfb8da71
3 changed files with 433 additions and 949 deletions

View File

@ -1,11 +1,15 @@
# Контекстно-свободная LIME-грамматика шаблонизатора # Контекстно-свободная LIME-грамматика шаблонизатора
# #
# ЗАМЕЧАНИЯ: # Для корректной работы нужен патченый LIME со следующими изменениями:
# (!) Для разбора нужен патченый LIME, в котором лексема 'lit' подменена на 'str'. # (*) Подменой лексемы 'lit' на 'str' в метаграмматике.
# Это нужно, чтобы можно было юзать строковые лексемы типа '<!--'. # Это нужно, чтобы можно было юзать строковые лексемы типа '<!--'.
# (*) Подразумевается, что лексический анализатор зависим от работы синтаксического, # (*) Для корректной обработки ошибок нужно, чтобы метод eat() возвращал
# знает о его состоянии и соответственно выдаёт либо лексемы "внутри" блоков кода, # false при ошибке и true при успехе. Т.к. подразумевается, что лексический
# либо литералы "вне" оных # анализатор зависим от работы синтаксического, знает о его состоянии и
# соответственно выдаёт либо лексемы "внутри" блоков кода, либо литералы
# "вне" оных.
#
# Кстати:
# (*) Олдстайл BEGIN .. END ликвидирован # (*) Олдстайл BEGIN .. END ликвидирован
# (*) Возможно, нужно добавить в каком-то виде foreach ... as key => value # (*) Возможно, нужно добавить в каком-то виде foreach ... as key => value
@ -19,9 +23,9 @@
%token ".." "concatenation operator '..'" %token ".." "concatenation operator '..'"
%token "||" "OR operator '||'" %token "||" "OR operator '||'"
%token "or" "OR operator 'OR'" %token "OR" "OR operator 'OR'"
%token "xor" "XOR operator 'XOR'" %token "XOR" "XOR operator 'XOR'"
%token "and" "AND operator 'AND'" %token "AND" "AND operator 'AND'"
%token "&&" "AND operator '&&'" %token "&&" "AND operator '&&'"
%token "&" "bitwise AND operator '&'" %token "&" "bitwise AND operator '&'"
%token "==" "equality operator '=='" %token "==" "equality operator '=='"
@ -38,7 +42,7 @@
%token "(" "left round brace '('" %token "(" "left round brace '('"
%token ")" "right round brace '('" %token ")" "right round brace '('"
%token "!" "NOT operator '!'" %token "!" "NOT operator '!'"
%token "not" "NOT operator 'NOT'" %token "NOT" "NOT operator 'NOT'"
%token "{" "left curly brace '{'" %token "{" "left curly brace '{'"
%token "}" "right curly brace '}'" %token "}" "right curly brace '}'"
%token "," "comma ','" %token "," "comma ','"
@ -49,8 +53,8 @@
%token "-->" "directive end '-->'" %token "-->" "directive end '-->'"
%left ".." %left ".."
%left "||" "or" "xor" %left "||" "OR" "XOR"
%left "&&" "and" %left "&&" "AND"
%nonassoc "==" "!=" "<" ">" "<=" ">=" %nonassoc "==" "!=" "<" ">" "<=" ">="
%left "+" "-" %left "+" "-"
%left "&" %left "&"
@ -80,7 +84,6 @@ chunk = literal {
$$ = '$t .= ' . $e . ";\n"; $$ = '$t .= ' . $e . ";\n";
} }
| error/e { | error/e {
$this->template->lexer->skip_error($e);
$$ = ''; $$ = '';
} }
. .
@ -88,16 +91,16 @@ code_chunk = c_if/$ | c_set/$ | c_fn/$ | c_for/$ | exp {
$$ = '$t .= ' . $1 . ";\n"; $$ = '$t .= ' . $1 . ";\n";
} }
. .
c_if = "if" exp/e "-->" chunks/if "<!--" "end" { c_if = "IF" exp/e "-->" chunks/if "<!--" "END" {
$$ = "if (" . $e . ") {\n" . $if . "}\n"; $$ = "if (" . $e . ") {\n" . $if . "}\n";
} }
| "if" exp/e "-->" chunks/if "<!--" "else" "-->" chunks/else "<!--" "end" { | "IF" exp/e "-->" chunks/if "<!--" "ELSE" "-->" chunks/else "<!--" "END" {
$$ = "if (" . $e . ") {\n" . $if . "} else {\n" . $else . "}\n"; $$ = "if (" . $e . ") {\n" . $if . "} else {\n" . $else . "}\n";
} }
| "if" exp/e "-->" chunks/if c_elseifs/ei chunks/ec "<!--" "end" { | "IF" exp/e "-->" chunks/if c_elseifs/ei chunks/ec "<!--" "END" {
$$ = "if (" . $e . ") {\n" . $if . $ei . $ec . "}\n"; $$ = "if (" . $e . ") {\n" . $if . $ei . $ec . "}\n";
} }
| "if" exp/e "-->" chunks/if c_elseifs/ei chunks/ec "<!--" "else" "-->" chunks/else "<!--" "end" { | "IF" exp/e "-->" chunks/if c_elseifs/ei chunks/ec "<!--" "ELSE" "-->" chunks/else "<!--" "END" {
$$ = "if (" . $e . ") {\n" . $if . $ei . $ec . "} else {\n" . $else . "}\n"; $$ = "if (" . $e . ") {\n" . $if . $ei . $ec . "} else {\n" . $else . "}\n";
} }
. .
@ -108,10 +111,10 @@ c_elseifs = "<!--" elseif exp/e "-->" {
$$ = $p . $cs . "} elseif (" . $e . ") {\n"; $$ = $p . $cs . "} elseif (" . $e . ") {\n";
} }
. .
c_set = "set" varref/v "=" exp/e { c_set = "SET" varref/v "=" exp/e {
$$ = $v . ' = ' . $e . ";\n"; $$ = $v . ' = ' . $e . ";\n";
} }
| "set" varref/v "-->" chunks/cs "<!--" "end" { | "SET" varref/v "-->" chunks/cs "<!--" "END" {
$$ = "\$stack[] = \$t;\n\$t = '';\n" . $cs . $v . " = \$t;\narray_pop(\$stack);\n"; $$ = "\$stack[] = \$t;\n\$t = '';\n" . $cs . $v . " = \$t;\narray_pop(\$stack);\n";
} }
. .
@ -125,7 +128,7 @@ c_fn = fn name/name "(" arglist/args ")" "=" exp/exp {
); );
$$ = ''; $$ = '';
} }
| fn name/name "(" arglist/args ")" "-->" chunks/cs "<!--" "end" { | fn name/name "(" arglist/args ")" "-->" chunks/cs "<!--" "END" {
$this->template->st->functions[$name] = array( $this->template->st->functions[$name] = array(
'name' => $name, 'name' => $name,
'args' => $args, 'args' => $args,
@ -136,7 +139,7 @@ c_fn = fn name/name "(" arglist/args ")" "=" exp/exp {
$$ = ''; $$ = '';
} }
. .
c_for = for varref/varref "=" exp/exp "-->" chunks/cs "<!--" "end" { c_for = for varref/varref "=" exp/exp "-->" chunks/cs "<!--" "END" {
$varref_index = substr($varref, 0, -1) . ".'_index']"; $varref_index = substr($varref, 0, -1) . ".'_index']";
$$ = "\$stack[] = ".$varref."; $$ = "\$stack[] = ".$varref.";
\$stack[] = ".$varref_index."; \$stack[] = ".$varref_index.";
@ -151,9 +154,9 @@ array_pop(\$stack);
"; ";
} }
. .
fn = "function" | "block" | "macro" . fn = "FUNCTION" | "BLOCK" | "MACRO" .
for = "for" | "foreach" . for = "FOR" | "FOREACH" .
elseif = "else" "if" | "elsif" | "elseif" . elseif = "ELSE" "IF" | "ELSIF" | "ELSEIF" .
# Выражения # Выражения
@ -163,16 +166,16 @@ exp: exp/a ".." exp/b {
| exp/a "||" exp/b { | exp/a "||" exp/b {
$$ = 'self::perlish_or(' . $a . ', ' . $b . ')'; $$ = 'self::perlish_or(' . $a . ', ' . $b . ')';
} }
| exp/a "or" exp/b { | exp/a "OR" exp/b {
$$ = 'self::perlish_or(' . $a . ', ' . $b . ')'; $$ = 'self::perlish_or(' . $a . ', ' . $b . ')';
} }
| exp/a "xor" exp/b { | exp/a "XOR" exp/b {
$$ = '(' . $a . ' XOR ' . $b . ')'; $$ = '(' . $a . ' XOR ' . $b . ')';
} }
| exp/a "&&" exp/b { | exp/a "&&" exp/b {
$$ = '(' . $a . ' && ' . $b . ')'; $$ = '(' . $a . ' && ' . $b . ')';
} }
| exp/a "and" exp/b { | exp/a "AND" exp/b {
$$ = '(' . $a . ' && ' . $b . ')'; $$ = '(' . $a . ' && ' . $b . ')';
} }
| exp/a "==" exp/b { | exp/a "==" exp/b {
@ -225,7 +228,7 @@ p11: nonbrace
| '!' p11/a { | '!' p11/a {
$$ = '(!'.$a.')'; $$ = '(!'.$a.')';
} }
| "not" p11/a { | "NOT" p11/a {
$$ = '(!'.$a.')'; $$ = '(!'.$a.')';
} }
. .

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,8 @@
%token name %token name
%left ".." %left ".."
%left "||" "or" "xor" %left "||" "OR" "XOR"
%left "&&" "and" %left "&&" "AND"
%nonassoc "==" "!=" "<" ">" "<=" ">=" %nonassoc "==" "!=" "<" ">" "<=" ">="
%left "+" "-" %left "+" "-"
%left "&" %left "&"
@ -22,21 +22,21 @@
chunks: | chunks chunk chunks: | chunks chunk
chunk: literal | "<!--" code_chunk "-->" | "{" exp "}" | error chunk: literal | "<!--" code_chunk "-->" | "{" exp "}" | error
code_chunk: c_if | c_set | c_fn | c_for | exp code_chunk: c_if | c_set | c_fn | c_for | exp
c_if: "if" exp "-->" chunks "<!--" "end" | c_if: "IF" exp "-->" chunks "<!--" "END" |
"if" exp "-->" chunks "<!--" "else" "-->" chunks "<!--" "end" | "IF" exp "-->" chunks "<!--" "ELSE" "-->" chunks "<!--" "END" |
"if" exp "-->" chunks c_elseifs chunks "<!--" "end" | "IF" exp "-->" chunks c_elseifs chunks "<!--" "END" |
"if" exp "-->" chunks c_elseifs chunks "<!--" "else" "-->" chunks "<!--" "end" "IF" exp "-->" chunks c_elseifs chunks "<!--" "ELSE" "-->" chunks "<!--" "END"
c_elseifs: "<!--" elseif exp "-->" | c_elseifs chunks "<!--" elseif exp "-->" c_elseifs: "<!--" elseif exp "-->" | c_elseifs chunks "<!--" elseif exp "-->"
c_set: "set" varref "=" exp | "set" varref "-->" chunks "<!--" "end" c_set: "SET" varref "=" exp | "SET" varref "-->" chunks "<!--" "END"
c_fn: fn name "(" arglist ")" "=" exp | fn name "(" arglist ")" "-->" chunks "<!--" "end" c_fn: fn name "(" arglist ")" "=" exp | fn name "(" arglist ")" "-->" chunks "<!--" "END"
c_for: for varref "=" exp "-->" chunks "<!--" "end" c_for: for varref "=" exp "-->" chunks "<!--" "END"
fn: "function" | "block" | "macro" fn: "FUNCTION" | "BLOCK" | "MACRO"
for: "for" | "foreach" for: "FOR" | "FOREACH"
elseif: "else" "if" | "elsif" | "elseif" elseif: "ELSE" "IF" | "ELSIF" | "ELSEIF"
exp: exp ".." exp | exp: exp ".." exp |
exp "||" exp | exp "or" exp | exp "xor" exp | exp "||" exp | exp "OR" exp | exp "XOR" exp |
exp "&&" exp | exp "and" exp | exp "&&" exp | exp "AND" exp |
exp "==" exp | exp "!=" exp | exp "==" exp | exp "!=" exp |
exp "<" exp | exp ">" exp | exp "<=" exp | exp ">=" exp | exp "<" exp | exp ">" exp | exp "<=" exp | exp ">=" exp |
exp "+" exp | exp "-" exp | exp "+" exp | exp "-" exp |
@ -44,7 +44,7 @@ exp: exp ".." exp |
exp "*" exp | exp "/" exp | exp "%" exp | exp "*" exp | exp "/" exp | exp "%" exp |
p10 p10
p10: p11 | '-' p11 p10: p11 | '-' p11
p11: nonbrace | '(' exp ')' varpath | '!' p11 | "not" p11 p11: nonbrace | '(' exp ')' varpath | '!' p11 | "NOT" p11
nonbrace: '{' hash '}' | literal | varref | name '(' ')' | name '(' list ')' | name '(' gthash ')' | name nonbrace | method '(' ')' | method '(' list ')' nonbrace: '{' hash '}' | literal | varref | name '(' ')' | name '(' list ')' | name '(' gthash ')' | name nonbrace | method '(' ')' | method '(' list ')'
method: varref '.' name method: varref '.' name
list: exp | exp ',' list list: exp | exp ',' list