空規則?の扱い

#!/usr/bin/env python

import ply.lex as lex

tokens = (
  'A',
)

t_A = r'A'
t_ignore = " \t"

def t_error(t):
    print "Illegal character '%s'" % t.value[0]
    t.lexer.skip(1)

lex.lex()


import ply.yacc as yacc

def p_input(p):
    '''input : 
             | A'''
    if (len(p) > 1): print p[1]

def p_error(p):
    print "Syntax error at '%s'" % p.value

yacc.yacc()


while 1:
    try:
        s = raw_input('input > ')
    except EOFError:
        break
    #if not s: continue
    #if not s: s = ""
    yacc.parse(s)

で、

input > A
A
input > 
input > 

最初にエンターを入力すると以下のようにエラーになってしまうようだ(理由不明。先読みまわりで???)

input > 
Traceback (most recent call last):
  File "./20080410_ply00.py", line 39, in ?
    yacc.parse(s)
  File "/usr/lib/python2.3/site-packages/ply/yacc.py", line 237, in parse
    lookahead = get_token()     # Get the next token
  File "/usr/lib/python2.3/site-packages/ply/lex.py", line 342, in token
    raise RuntimeError, "No input string given with input()"
RuntimeError: No input string given with input()


空ルールを削除すると、

#!/usr/bin/env python

import ply.lex as lex

tokens = (
  'A',
)

t_A = r'A'
t_ignore = " \t"

def t_error(t):
    print "Illegal character '%s'" % t.value[0]
    t.lexer.skip(1)

lex.lex()


import ply.yacc as yacc

def p_input(p):
    '''input : A'''
    print p[1]

def p_error(p):
    print "Syntax error at '%s'" % p.value

yacc.yacc()


while 1:
    try:
        s = raw_input('input > ')
    except EOFError:
        break
    #if not s: continue
    yacc.parse(s)

で、

input > A
A
input > 
Traceback (most recent call last):
  File "./20080410_ply01.py", line 37, in ?
    yacc.parse(s)
  File "/usr/lib/python2.3/site-packages/ply/yacc.py", line 346, in parse
    tok = self.errorfunc(errtoken)
  File "./20080410_ply01.py", line 26, in p_error
    print "Syntax error at '%s'" % p.value
AttributeError: 'NoneType' object has no attribute 'value'


empty を書いた方が読みやすいと言っているようだけど、empty というルールがあらかじめ用意されているわけでもないようだ。

#!/usr/bin/env python

import ply.lex as lex

tokens = (
  'A',
)

t_A = r'A'
t_ignore = " \t"

def t_error(t):
    print "Illegal character '%s'" % t.value[0]
    t.lexer.skip(1)

lex.lex()


import ply.yacc as yacc

def p_input(p):
    '''input : empty
             | A'''
    if (len(p) > 1): print p[1]

def p_error(p):
    print "Syntax error at '%s'" % p.value

yacc.yacc()


while 1:
    try:
        s = raw_input('input > ')
    except EOFError:
        break
    #if not s: continue
    #if not s: s = ""
    yacc.parse(s)

で、

./20080410_ply02.py:22: Symbol 'empty' used, but not defined as a token or a rule.
Traceback (most recent call last):
  File "./20080410_ply02.py", line 29, in ?
    yacc.yacc()
  File "/usr/lib/python2.3/site-packages/ply/yacc.py", line 2156, in yacc
    raise YaccError,"Unable to construct parser."
ply.yacc.YaccError: Unable to construct parser.


以下のように自分で empty というのを定義。
別に empty なんていらないのでは?と思わないでもない。

#!/usr/bin/env python

import ply.lex as lex

tokens = (
  'A',
)

t_A = r'A'
t_ignore = " \t"

def t_error(t):
    print "Illegal character '%s'" % t.value[0]
    t.lexer.skip(1)

lex.lex()


import ply.yacc as yacc

def p_input(p):
    '''input : empty
             | A'''
    if (len(p) > 1): print p[1]

def p_empty(p):
    'empty :'
    pass

def p_error(p):
    print "Syntax error at '%s'" % p.value

yacc.yacc()


while 1:
    try:
        s = raw_input('input > ')
    except EOFError:
        break
    #if not s: continue
    #if not s: s = ""
    yacc.parse(s)

で、

input > A
A
input > 
None
input > 
None