Ply und newlines

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
lunas
User
Beiträge: 87
Registriert: Samstag 2. Dezember 2006, 10:56

Freitag 26. Dezember 2008, 06:06

Hallo,

ich versuche gerade einen Compiler für ein paar Regeln zu schreiben. Der Syntax der Regeln sieht folgendermaßen an einem Beispiel erklärt aus:

Code: Alles auswählen

A = 1{B,C} & 2{D,E,F}
F = 1{G}
Regel 'A' ist erfüllt, wenn Regel B oder C und 2 Regeln der Menge {D,E,F} erfüllt sind. Der Parser funktioniert soweit auch ganz gut, aber bei vorhandenen newlines bricht er mit einer Fehlermeldung ab. Wenn ich die 2. Zeile des obigen Beispiels mit # auskommentiere, dann klappt es mit dem Erkennen der 1. Regel.

Code: Alles auswählen

import ply.lex as lex
import ply.yacc as yacc
import os
import sys

rules = """
A = 1{B,C} & 2{D,E,F}
F = 1{G}
"""

tokens = (
  'NUMBER',  'NAME',  'OPEN_BRACE',  'CLOSE_BRACE',  'COMMA',  'AND',  'EQUALS',  #'NEWLINE',
)

t_ignore = " \r\t+~[].|!?%@"
t_NUMBER = r'[0-9][0-9XxA-Fa-f]*'
t_NAME = r'[<>A-Za-z_][A-Za-z0-9_]*'
t_OPEN_BRACE = r'{'
t_CLOSE_BRACE = r'}'
t_COMMA = r','
t_AND = r'&'
t_EQUALS = r'='

def t_NEWLINE(t):
  r'\n+'
  t.lexer.lineno += len(t.value)  
  
def t_comment(s):
  r'\#.*'

def t_error(t):
  raise TypeError("Unknown text '%s'" % (t.value,))


lex.lex()

class Rule(object):
  def __init__(self, rule, prereq):
    self.rule = rule
    self.prereq = prereq
    
  def __repr__(self):
    return "Rule(%s, %s)" % (self.rule, self.prereq)


class Prereq(object):
  def __init__(self, count, rule_list):
    self.rule_list = rule_list
    self.count = count
    
  def __repr__(self):
    return "Prereq(%s, %s)" % (self.count, self.rule_list)


def p_rule_prereq(p):
  """
  rule_prereq :    
  rule_prereq : NAME EQUALS prereq_list
  """  
  if len(p) == 1 or len(p) == 2:
    p[0] = []
  else:    
    p[0] = Rule(p[1], p[3])
  print'catch'

def p_prereq_list(p):
  """
  prereq_list : prereq
  prereq_list : prereq_list AND prereq
  """
  if len(p) == 2:
    p[0] = [p[1]]
  elif len(p) == 4:
    p[0] = p[1] + [p[3]]
    

def p_rule_list(p):
  """
  rule_list : rule_list COMMA rule
  rule_list : rule  
  """
  if len(p) == 4:
    p[0] = p[1] + p[3]
  elif len(p) == 2:
    p[0] = p[1]
  

def p_prereq(p):
  "prereq : NUMBER OPEN_BRACE rule_list CLOSE_BRACE"
  p[0] = Prereq(p[1], p[3])
  


def p_rule(p):
  "rule : NAME"
  p[0] = [p[1]]

        
def p_error(p):
    raise TypeError("unknown text at %r" % (p,))
    
yacc.yacc()


print yacc.parse(rules)
Die Fehlermeldung lautet:

Code: Alles auswählen

yacc: Generating LALR parsing table...
Traceback (most recent call last):
  File "rule.py", line 120, in <module>
    print yacc.parse(rules) 
  File "build\bdist.win32\egg\ply\yacc.py", line 346, in parse
  File "rule.py", line 115, in p_error
    raise TypeError("unknown text at %r" % (p,))
TypeError: unknown text at LexToken(NAME,'F',3,23)
Muss ich newline in eine der Regeln mit aufnehmen (wahrscheinlich in p_rule_prereq) und dann eine leere Liste zurückgeben (habe ich auch schon versucht, aber hat zum gleichen Ergebnis geführt)?

Vielleicht weiß ja jemand Rat.

lunas
lunas
User
Beiträge: 87
Registriert: Samstag 2. Dezember 2006, 10:56

Freitag 26. Dezember 2008, 09:11

Das Problem hat sich glaube ich erledigt. Man darf den Parser nur mit einer Textzeile nach der anderen füttern, dann klappt es auch.
Antworten