У нас есть небольшие фрагменты кода vb6 (единственное использование подмножества функций), которые пишут непрограммисты. Это называется правила. Для людей, пишущих их, их трудно отлаживать, поэтому кто-то написал своего рода дополнительный синтаксический анализатор, чтобы иметь возможность оценивать подвыражения и тем самым лучше показывать, где проблема.
Этот парсер addhoc очень плохой и на самом деле не работает. Итак, я пытаюсь написать настоящий синтаксический анализатор (потому что я пишу его вручную (без генератора синтаксического анализа, который я мог бы понять с бэкэндами vb6). Я хочу использовать рекурсивный приличный парсер). Мне пришлось перепроектировать грамматик, потому что я мог найти что угодно. (В конце концов я нашел что-то http://www.notebar.com/GoldParserEngine.html, но это LALR и он намного больше, чем мне нужно)
Вот грамматик для подмножества VB.
<Rule> ::= expr rule | e
<Expr> ::= ( expr )
| Not_List CompareExpr <and_or> expr
| Not_List CompareExpr
<and_or> ::= Or | And
<Not_List> ::= Not Not_List | e
<CompareExpr> ::= ConcatExpr comp CompareExpr
|ConcatExpr
<ConcatExpr> ::= term term_tail & ConcatExpr
|term term_tail
<term> ::= factor factor_tail
<term_tail> ::= add_op term term_tail | e
<factor> ::= add_op Value | Value
<factor_tail> ::= multi_op factor factor_tail | e
<Value> ::= ConstExpr | function | expr
<ConstExpr> ::= <bool> | number | string | Nothing
<bool> ::= True | False
<Nothing> ::= Nothing | Null | Empty
<function> ::= id | id ( ) | id ( arg_list )
<arg_list> ::= expr , arg_list | expr
<add_op> ::= + | -
<multi_op> ::= * | /
<comp> ::= > | < | <= | => | =< | >= | = | <>
В целом, это работает довольно хорошо, вот несколько простых примеров:
my_function(1, 2 , 3)
похоже
(Programm
(rule
(expr
(Not_List)
(CompareExpr
(ConcatExpr
(term
(factor
(value
(function
my_function
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 1))) (term_tail))))
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 2))) (term_tail))))
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 3))) (term_tail))))
(arg_list))))))))
(term_tail))))
(rule)))
Теперь в чем моя проблема?
если у вас есть код, похожий на этот (( true OR false ) AND true)
, у меня бесконечная рекурсия, но настоящая проблема в том, что в (true OR false) AND true
(после первого ( expr )
) понимается только (true or false)
.
Вот Parstree:
Итак, как решить эту проблему. Должен ли я как-то изменить грамматик или использовать какой-то имплементационный хак?
Что-то сложное exmplale в случае, если вам это нужно.
(( f1 OR f1 ) AND (( f3="ALL" OR f4="test" OR f5="ALL" OR f6="make" OR f9(1, 2) ) AND ( f7>1 OR f8>1 )) OR f8 <> "")
left-recursion
. - person Karl Knechtel   schedule 08.07.2011