Depuração pyparsing Grammar
Pergunta
Eu estou construindo um analisador para uma linguagem de programação imaginário chamado C-- (não a língua C-- real). Eu chegar ao estágio onde eu preciso traduzir a gramática da linguagem em algo pyparsing pode aceitar. Infelizmente quando eu venho para analisar a minha cadeia de entrada (o que é correto e não deve causar pyparsing de erro) não é analisar corretamente. Temo que isso é devido a erros na minha gramática, mas como eu estou começando pyparsing pela primeira vez, eu não consigo ver onde estou indo errado.
Eu transferiu a gramática que eu estou traduzindo do aqui para as pessoas a ter um ler.
EDIT:. Atualizado com o conselho de Paulo
Esta é a gramática que eu tenho atualmente (as duas linhas principais de definição de sintaxe são terrivelmente ruim de mim eu sei):
# 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)
Eu gostaria de saber se existem quaisquer erros que eu fiz em traduzir a gramática toda e que melhorias eu poderia fazer para torná-lo simplificado enquanto aderindo à gramática que me foi dada.
EDIT 2:. Atualizado para incluir o novo erro
Aqui está a seqüência de entrada Eu estou analisando:
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 ) ;
}
E esta é a mensagem de erro que recebo quando executar o meu programa de Terminal:
/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
Solução
1) Mudança Literal("if")
para Keyword("if")
(e assim por diante, até Literal("void")
), para evitar combinando o líder "se" de uma variável chamada "ifactor"
.
2) nums
, alphas
e alphanums
não são expressões, que são seqüências, que podem ser usados ??com a classe Word para definir alguns conjuntos típicos de caracteres na definição de "palavras" como "um número é uma palavra composta de nums ", ou 'um identificador é uma palavra que começa com um alfa, seguido de zero ou mais alfanuméricos.' Assim em vez de:
number = nums
identifier = alphas + OneOrMore(alphanums)
Você quer
number = Word(nums)
identifier = Word(alphas, alphanums)
3) Em vez de Combine
, eu acho que você quer Group
. Use Combine
quando você quer os sinais combinados para ser contíguo com nenhum espaço em branco intervir, e concatenar os tokens e devolvê-los como uma única seqüência. Combine
é frequentemente usado em casos como este:
realnum = Combine(Word(nums) + "." + Word(nums))
Sem Combine
, analisar "3.14"
voltaria a lista de strings ['3', '.', '14']
, então adicionamos Combine
para que o resultado analisado para realnum é '3.14'
(que você pode então passar para uma ação de análise para converter ao 3.14
real valor flutuante). Combine
s execução de nenhum espaço em branco intervir também nos impede de acidentalmente analisar 'The answer is 3. 10 is too much.'
e pensar o "3. 10"
representa um número real.
4) Isso não deve causar o seu erro, mas a sua cadeia de entrada tiver muitos de espaços extras. Se você começar o seu trabalho de gramática, você deve ser capaz de "int x;"
parse tão bem como "int x ;"
.
Hope algumas dessas dicas você ir. Você já leu todos os artigos pyparsing online ou tutoriais? E, por favor olhar através dos exemplos on-line. Você precisa ter uma boa idéia de como Word
, Literal
, Combine
, etc. executar suas tarefas de análise individuais.
5) Você tem mis-implementou as definições recursivas para o termo e comunicado. Em vez de atribuir ''
a eles, escreve:
term = Forward()
statement = Forward()
Então, quando você vai para realmente defini-los com as suas definições recursivas, use o operador <<
(e não se esqueça de incluir o RHS em ()
de).
term << (... term definition ...)
statement << (... statement definition ...)
Você pode encontrar um exemplo de um analisador de recursiva aqui , e uma apresentação sobre o uso pyparsing básica aqui - consulte a secção intitulado "a análise de listas" para mais passo-a-passo sobre como a recursividade é tratada.