Seite 1 von 1

Ply und newlines

Verfasst: Freitag 26. Dezember 2008, 06:06
von lunas
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

Verfasst: Freitag 26. Dezember 2008, 09:11
von lunas
Das Problem hat sich glaube ich erledigt. Man darf den Parser nur mit einer Textzeile nach der anderen füttern, dann klappt es auch.