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
Foi útil?

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). Combines 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top