Подтвердить что ты не робот

Отладка грамматики Pyparsing

Я создаю парсер для воображаемого языка программирования C-- (а не C-языка). Я попал на сцену, где мне нужно перевести грамматику языка во что-то, что может принять Pyparsing. К сожалению, когда я пришел, чтобы разобрать мою строку ввода (что правильно и не должно приводить к ошибке Pyparsing), он не разбирается правильно. Я боюсь, что это связано с ошибками в моей грамматике, но поскольку я начинаю Pyparsing в первый раз, я не могу видеть, где я ошибаюсь.

Я загрузил грамматику, которую я переводил из здесь, чтобы люди могли прочитать.

РЕДАКТИРОВАТЬ: Обновлено с помощью совета Павла.

Это грамматик, который я сейчас получил (две верхние строки определения синтаксиса ужасно плохи из меня, которых я знаю):

# Lexical structure definition
ifS = Keyword('if')
elseS = Keyword('else')
whileS = Keyword('while')
returnS = Keyword('return')
intVar = Keyword('int')
voidKeyword = Keyword('void')
sumdiff = Literal('+') | Literal('-')
prodquot = Literal('*') | Literal('/')
relation = Literal('<=') | Literal('<') | Literal('==') | \
           Literal('!=') | Literal('>') | Literal('=>')
lbrace = Literal('{')
rbrace = Literal('}')
lparn = Literal('(')
rparn = Literal(')')
semi = Literal(';')
comma = Literal(',')
number = Word(nums)
identifier = Word(alphas, alphanums)

# Syntax definition
term = ''
statement = ''
variable    =   intVar + identifier + semi
locals      =   ZeroOrMore(variable)
expr        =   term | OneOrMore(Group(sumdiff + term))
args        =   ZeroOrMore(OneOrMore(Group(expr + comma)) | expr)
funccall    =   Group(identifier + lparn + args + rparn)
factor      =   Group(lparn + expr + rparn) | identifier | funccall | number
term        =   factor | OneOrMore(prodquot + factor)
cond        =   Group(lparn + expr + relation + expr + rparn)
returnState =   Group(returnS + semi) | Combine(returnS + expr + semi)
assignment  =   Group(identifier + '=' + expr + semi)
proccall    =   Group(identifier + lparn + args + rparn + semi)
block       =   Group(lbrace + locals + statement + rbrace)
iteration   =   Group(whileS + cond + block)
selection   =   Group(ifS + cond + block) | Group(ifS + cond + block + elseS + block)
statement   =   OneOrMore(proccall | assignment | selection | iteration | returnState)
param       =   Group(intVar + identifier)
paramlist   =   OneOrMore(Combine(param + comma)) | param
params      =   paramlist | voidKeyword
procedure   =   Group(voidKeyword + identifier + lparn + params + rparn + block)
function    =   Group(intVar + identifier + lparn + params + rparn + block)
declaration =   variable | function | procedure
program     =   OneOrMore(declaration)

Я хотел бы знать, есть ли какие-либо ошибки в переводе грамматики и какие улучшения я могу сделать, чтобы упростить ее, придерживаясь грамматики, которую мне дали.

EDIT 2: Обновлен, чтобы включить новую ошибку.

Вот строка ввода, которую я обрабатываю:

int larger ( int first , int second ) { 
if ( first > second ) { 
return first ; 
} else { 
return second ; 
} 
} 

void main ( void ) { 
int count ; 
int sum ; 
int max ; 
int x ; 

x = input ( ) ; 
max = x ; 
sum = 0 ; 
count = 0 ; 

while ( x != 0 ) { 
count = count + 1 ; 
sum = sum + x ; 
max = larger ( max , x ) ; 
x = input ( ) ; 
} 

output ( count ) ; 
output ( sum ) ; 
output ( max ) ; 
} 

И это сообщение об ошибке, которое я получаю при запуске моей программы из терминала:

/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1156: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
/Users/Joe/Documents/Eclipse Projects/Parser/src/pyparsing.py:1258: SyntaxWarning: null string passed to Literal; use Empty() instead
other = Literal( other )
Expected ")" (at char 30), (line:6, col:26)
None
4b9b3361

Ответ 1

1) Измените Literal("if") на Keyword("if") (и так далее, вплоть до Literal("void")), чтобы избежать совпадения ведущей "if" переменной с именем "ifactor".

2) nums, alphas и alphanums не являются выражениями, они являются строками, которые могут использоваться с классом Word для определения некоторых типичных наборов символов при определении "слов" типа "число" слово, состоящее из nums ", или" идентификатор - это слово, которое начинается с альфы, за которым следуют ноль или несколько букв ". Поэтому вместо:

number = nums
identifier = alphas + OneOrMore(alphanums)

вы хотите

number = Word(nums)
identifier = Word(alphas, alphanums)

3) Вместо Combine, я думаю, вы хотите Group. Используйте Combine, если вы хотите, чтобы согласованные маркеры были смежными, без промежуточных пробелов, и объединяет маркеры и возвращает их как одну строку. Combine часто используется в следующих случаях:

realnum = Combine(Word(nums) + "." + Word(nums))

Без Combine, синтаксический анализ "3.14" вернет список строк ['3', '.', '14'], поэтому мы добавим Combine, чтобы результат синтаксического анализа для realnum был '3.14' (который затем можно передать в действие синтаксического анализа преобразовать в фактическое значение плавающего 3.14). Combine принудительное выполнение без промежуточных пробелов также препятствует случайному анализу 'The answer is 3. 10 is too much.' и думает, что "3. 10" представляет действительное число.

4) Это не должно вызывать ошибки, но ваша строка ввода содержит много лишних пробелов. Если вы используете свою грамматику, вы должны иметь возможность анализировать "int x;" так же, как и "int x ;".

Надеюсь, что некоторые из этих намеков заставят вас идти. Вы читали какие-либо онлайн-статьи или учебники для пиражей? И, пожалуйста, просмотрите онлайн-примеры. Вам нужно хорошо понять, как Word, Literal, Combine и т.д. Выполняют свои индивидуальные задачи синтаксического анализа.

5) Вы неправильно реализовали рекурсивные определения термина и утверждения. Вместо того, чтобы присваивать им '', напишите:

term = Forward()
statement = Forward()

Затем, когда вы идете, чтобы определить их с их рекурсивными определениями, используйте оператор << (и обязательно включите RHS в ()).

term << (... term definition ...)
statement << (... statement definition ...)

Вы можете найти пример рекурсивного синтаксического анализа здесь, а также презентацию об использовании основного пиража здесь - см. раздел "Списки раскладки" для более пошагового указания того, как обрабатывается рекурсия.