# $Id: krbparser.py 081917d30609 2010-03-05 mtnyogi $
# coding=utf-8
#
# Copyright 2007-2008 Bruce Frederiksen
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
""" See http://www.dabeaz.com/ply/ply.html for syntax of grammer definitions.
"""
from __future__ import with_statement
import itertools
import warnings
import os, os.path
from pyke.krb_compiler.ply import yacc
from pyke.krb_compiler import scanner
from pyke import pattern,contexts
tokens = scanner.tokens
goal_mode = False
def p_top(p):
''' top : file
| python_goal
'''
p[0] = p[1]
def p_goal(p):
''' python_goal : CHECK_TOK IDENTIFIER_TOK '.' IDENTIFIER_TOK LP_TOK patterns_opt RP_TOK
'''
p[0] = (p[2], p[4], p[6], pattern_vars)
def p_file(p):
''' file : nl_opt parent_opt fc_rules bc_rules_opt
'''
p[0] = ('file', p[2], (tuple(p[3]), ()), p[4])
def p_file_fc_extras(p):
''' file : nl_opt parent_opt fc_rules fc_extras bc_rules_opt
'''
p[0] = ('file', p[2], (tuple(p[3]), p[4]), p[5])
def p_file_bc(p):
''' file : nl_opt parent_opt bc_rules_section
'''
p[0] = ('file', p[2], ((), ()), p[3])
# Uncomment this to generate an error in the grammer.
#def p_bogus(p):
# ''' file : nl_opt parent_opt bc_rules_opt
# '''
# p[0] = ('file', p[2], ((), ()), p[3])
def p_parent(p):
''' parent_opt : EXTENDING_TOK IDENTIFIER_TOK without_opt NL_TOK
'''
p[0] = ('parent', p[2], tuple(p[3]))
def p_second(p):
''' without_opt : WITHOUT_TOK without_names comma_opt
'''
p[0] = p[2]
def p_fourth(p):
''' when_opt : WHEN_TOK NL_TOK reset_plan_vars INDENT_TOK bc_premises DEINDENT_TOK
'''
p[0] = p[5]
def p_reset_plan_vars(p):
''' reset_plan_vars :
'''
global plan_var, plan_var_number
plan_var_number = 1
plan_var = 'plan#%d' % plan_var_number
p[0] = None
def p_inc_plan_vars(p):
''' inc_plan_vars :
'''
global plan_var, plan_var_number
plan_var_number += 1
plan_var = 'plan#%d' % plan_var_number
p[0] = None
def p_fifth(p):
''' bc_extras_opt : BC_EXTRAS_TOK NL_TOK start_extra_statements INDENT_TOK python_extras_code NL_TOK DEINDENT_TOK
fc_extras : FC_EXTRAS_TOK NL_TOK start_extra_statements INDENT_TOK python_extras_code NL_TOK DEINDENT_TOK
plan_extras_opt : PLAN_EXTRAS_TOK NL_TOK start_extra_statements INDENT_TOK python_extras_code NL_TOK DEINDENT_TOK
with_opt : WITH_TOK NL_TOK start_python_statements INDENT_TOK python_plan_code NL_TOK DEINDENT_TOK
'''
p[0] = p[5]
def p_none(p):
''' bc_require_opt :
comma_opt :
comma_opt : ','
colon_opt :
data : NONE_TOK
fc_require_opt :
nl_opt :
nl_opt : NL_TOK
parent_opt :
plan_spec : NL_TOK
rest_opt : comma_opt
'''
p[0] = None
def p_colon_deprication(p):
''' colon_opt : ':'
'''
warnings.warn_explicit("use of ':' deprecated after rule names",
DeprecationWarning,
scanner.lexer.filename, p.lineno(1))
p[0] = None
def p_fc_rule(p):
''' fc_rule : IDENTIFIER_TOK colon_opt NL_TOK INDENT_TOK foreach_opt ASSERT_TOK NL_TOK INDENT_TOK assertions DEINDENT_TOK DEINDENT_TOK
'''
p[0] = ('fc_rule', p[1], p[5], tuple(p[9]))
def p_foreach(p):
''' foreach_opt : FOREACH_TOK NL_TOK INDENT_TOK fc_premises DEINDENT_TOK
'''
p[0] = tuple(p[4])
def p_fc_premise(p):
''' fc_premise : IDENTIFIER_TOK '.' IDENTIFIER_TOK LP_TOK patterns_opt RP_TOK NL_TOK
'''
p[0] = ('fc_premise', p[1], p[3], tuple(p[5]), p.lineno(1), p.lineno(6))
def p_fc_first_1(p):
''' fc_premise : FIRST_TOK NL_TOK INDENT_TOK fc_premises DEINDENT_TOK
'''
p[0] = ('fc_first', tuple(p[4]), p.lineno(1))
def p_fc_first_n(p):
''' fc_premise : FIRST_TOK fc_premise
'''
p[0] = ('fc_first', (p[2],), p.lineno(1))
def p_fc_notany(p):
''' fc_premise : NOTANY_TOK NL_TOK INDENT_TOK fc_premises DEINDENT_TOK
'''
p[0] = ('fc_notany', tuple(p[4]), p.lineno(1))
def p_fc_forall(p):
''' fc_premise : FORALL_TOK NL_TOK INDENT_TOK fc_premises DEINDENT_TOK fc_require_opt
'''
p[0] = ('fc_forall', tuple(p[4]), p[6], p.lineno(1), p.linespan(6)[1])
def p_fc_require_opt(p):
''' fc_require_opt : REQUIRE_TOK NL_TOK INDENT_TOK fc_premises DEINDENT_TOK
'''
p[0] = tuple(p[4])
def p_python_eq(p):
''' python_premise : pattern start_python_code '=' python_rule_code NL_TOK
'''
p[0] = ('python_eq', p[1], p[4], p.linespan(1)[0], p.linespan(4)[1])
def p_python_in(p):
''' python_premise : pattern start_python_code IN_TOK python_rule_code NL_TOK
'''
p[0] = ('python_in', p[1], p[4], p.linespan(1)[0], p.linespan(4)[1])
def p_python_check(p):
''' python_premise : start_python_code CHECK_TOK python_rule_code NL_TOK
'''
p[0] = ('python_check', p[3], p.lineno(2), p.linespan(3)[1])
def p_python_block_n(p):
''' python_premise : check_nl PYTHON_TOK NL_TOK start_python_assertion INDENT_TOK python_rule_code NL_TOK DEINDENT_TOK
'''
p[0] = ('python_block', p[6], p.lineno(2), p.linespan(6)[1])
def p_python_block_1(p):
''' python_premise : check_nl PYTHON_TOK start_python_code NOT_NL_TOK python_rule_code NL_TOK
'''
p[0] = ('python_block', p[5], p.lineno(2), p.linespan(5)[1])
def p_assertion(p):
''' assertion : IDENTIFIER_TOK '.' IDENTIFIER_TOK LP_TOK patterns_opt RP_TOK NL_TOK
'''
p[0] = ('assert', p[1], p[3], tuple(p[5]), p.lineno(1), p.lineno(6))
def p_python_assertion_n(p):
''' assertion : check_nl PYTHON_TOK NL_TOK start_python_assertion INDENT_TOK python_rule_code NL_TOK DEINDENT_TOK
'''
p[0] = ('python_assertion', p[6], p.lineno(2), p.linespan(6)[1])
def p_python_assertion_1(p):
''' assertion : check_nl PYTHON_TOK start_python_code NOT_NL_TOK python_rule_code NL_TOK
'''
p[0] = ('python_assertion', p[5], p.lineno(2), p.linespan(5)[1])
def p_check_nl(p):
''' check_nl :
'''
scanner.lexer.begin('checknl')
p[0] = None
def p_bc_rule(p):
''' bc_rule : IDENTIFIER_TOK colon_opt NL_TOK INDENT_TOK USE_TOK goal when_opt with_opt DEINDENT_TOK
'''
p[0] = ('bc_rule', p[1], p[6], tuple(p[7]), tuple(p[8][0]), tuple(p[8][1]))
def p_empty_bc_rules_opt(p):
''' bc_rules_opt :
'''
p[0] = ((), (), ())
def p_bc_rules_section(p):
''' bc_rules_section : bc_rules bc_extras_opt plan_extras_opt
'''
p[0] = (tuple(p[1]), p[2], p[3])
def p_goal_no_taking(p):
''' goal : IDENTIFIER_TOK LP_TOK patterns_opt RP_TOK NL_TOK
'''
p[0] = ('goal', p[1], tuple(p[3]), (), p.lineno(1), p.lineno(4))
def p_goal_taking(p):
''' goal : IDENTIFIER_TOK LP_TOK patterns_opt RP_TOK taking
'''
p[0] = ('goal', p[1], tuple(p[3]), p[5], p.lineno(1), p.lineno(4))
def p_name_sym(p):
''' name : IDENTIFIER_TOK
'''
p[0] = repr(p[1])
def p_name_pat_var(p):
''' name : PATTERN_VAR_TOK
'''
p[0] = "context.lookup_data(%s)" % p[1]
def p_bc_premise1(p):
''' bc_premise : name LP_TOK patterns_opt RP_TOK plan_spec
'''
p[0] = ('bc_premise', False, None, p[1], tuple(p[3]), p[5],
p.linespan(1)[0], p.lineno(4))
def p_bc_premise2(p):
''' bc_premise : '!' name LP_TOK patterns_opt RP_TOK plan_spec
'''
p[0] = ('bc_premise', True, None, p[2], tuple(p[4]), p[6],
p.lineno(1), p.lineno(5))
def p_bc_premise3(p):
''' bc_premise : name '.' name LP_TOK patterns_opt RP_TOK plan_spec
'''
p[0] = ('bc_premise', False, p[1], p[3], tuple(p[5]), p[7],
p.linespan(1)[0], p.lineno(6))
def p_bc_premise4(p):
''' bc_premise : '!' name '.' name LP_TOK patterns_opt RP_TOK plan_spec
'''
p[0] = ('bc_premise', True, p[2], p[4], tuple(p[6]), p[8],
p.lineno(1), p.lineno(7))
def p_bc_first_1f(p):
''' bc_premise : FIRST_TOK NL_TOK INDENT_TOK bc_premises DEINDENT_TOK
'''
p[0] = ('bc_first', False, tuple(p[4]), p.lineno(1))
def p_bc_first_nf(p):
''' bc_premise : FIRST_TOK bc_premise
'''
p[0] = ('bc_first', False, (p[2],), p.lineno(1))
def p_bc_first_1t(p):
''' bc_premise : '!' FIRST_TOK NL_TOK INDENT_TOK bc_premises DEINDENT_TOK
'''
p[0] = ('bc_first', True, tuple(p[4]), p.lineno(1))
def p_bc_first_nt(p):
''' bc_premise : '!' FIRST_TOK bc_premise
'''
p[0] = ('bc_first', True, (p[2],), p.lineno(1))
def p_bc_notany(p):
''' bc_premise : NOTANY_TOK NL_TOK INDENT_TOK bc_premises DEINDENT_TOK
'''
p[0] = ('bc_notany', tuple(p[4]), p.lineno(1))
def p_bc_forall(p):
''' bc_premise : FORALL_TOK NL_TOK INDENT_TOK bc_premises DEINDENT_TOK bc_require_opt
'''
p[0] = ('bc_forall', tuple(p[4]), p[6], p.lineno(1), p.linespan(6)[1])
def p_bc_require_opt(p):
''' bc_require_opt : REQUIRE_TOK NL_TOK INDENT_TOK bc_premises DEINDENT_TOK
'''
p[0] = tuple(p[4])
def p_as(p):
''' plan_spec : AS_TOK PATTERN_VAR_TOK NL_TOK
'''
p[0] = ('as', p[2][1:-1])
def p_step_code(p):
''' plan_spec : STEP_TOK NUMBER_TOK NL_TOK start_python_plan_call INDENT_TOK python_plan_code NL_TOK DEINDENT_TOK
'''
p[0] = ('plan_spec', p[2], plan_var, p[6][0], p[6][1],
p.lineno(1), p.lexpos(1))
def p_code(p):
''' plan_spec : NL_TOK start_python_plan_call INDENT_TOK python_plan_code NL_TOK DEINDENT_TOK
'''
p[0] = ('plan_spec', None, plan_var, p[4][0], p[4][1], p[4][2], p[4][3])
def p_start_python_code(p):
''' start_python_code :
'''
scanner.start_code(var_format = "context.lookup_data('%s')")
p[0] = None
def p_start_python_plan_call(p):
''' start_python_plan_call :
'''
scanner.start_code(plan_name = plan_var, multiline = True)
p[0] = None
def p_start_python_statements(p):
''' start_python_statements :
'''
scanner.start_code(multiline = True)
p[0] = None
def p_start_extra_statements(p):
''' start_extra_statements :
'''
scanner.start_code(multiline = True, var_format = None)
p[0] = None
def p_start_python_assertion(p):
''' start_python_assertion :
'''
scanner.start_code(multiline = True,
var_format = "context.lookup_data('%s')")
p[0] = None
def p_python_rule_code(p):
''' python_rule_code : CODE_TOK
'''
p[0] = p[1]
def p_python_plan_code(p):
''' python_plan_code : CODE_TOK
'''
p[0] = p[1]
def p_python_extras_code(p):
''' python_extras_code : CODE_TOK
'''
p[0] = p[1][0]
def p_pattern_var(p):
''' variable : PATTERN_VAR_TOK
'''
global pattern_vars
if goal_mode:
pattern_vars.append(p[1])
p[0] = contexts.variable(p[1])
else:
p[0] = "contexts.variable(%s)" % p[1]
def p_anonymous_var(p):
''' variable : ANONYMOUS_VAR_TOK
'''
if goal_mode:
p[0] = contexts.anonymous(p[1])
else:
p[0] = "contexts.anonymous(%s)" % p[1]
def p_first(p):
''' bc_premise : python_premise
bc_rules_opt : bc_rules_section
data : NUMBER_TOK
fc_premise : python_premise
pattern : pattern_proper
pattern_proper : variable
patterns_opt : patterns comma_opt
'''
p[0] = p[1]
def p_last(p):
''' rest_opt : ',' '*' variable
'''
p[0] = p[len(p)-1]
def p_data_string(p):
''' data : STRING_TOK
'''
if goal_mode:
if p[1].startswith("'''") or p[1].startswith('"""'):
p[0] = scanner.unescape(p[1][3:-3])
else:
p[0] = scanner.unescape(p[1][1:-1])
else:
p[0] = p[1]
def p_taking(p):
''' taking : start_python_code TAKING_TOK python_rule_code NL_TOK
'''
p[0] = p[3][0]
def p_taking2(p):
''' taking : NL_TOK INDENT_TOK start_python_code TAKING_TOK python_rule_code NL_TOK DEINDENT_TOK
'''
p[0] = p[5][0]
def p_quoted_last(p):
''' data : IDENTIFIER_TOK
'''
if goal_mode:
p[0] = p[len(p)-1]
else:
p[0] = "'" + p[len(p)-1] + "'"
def p_false(p):
''' data : FALSE_TOK
'''
p[0] = False
def p_true(p):
''' data : TRUE_TOK
'''
p[0] = True
def p_start_list(p):
''' assertions : assertion
bc_premises : bc_premise
bc_rules : bc_rule
data_list : data
fc_premises : fc_premise
fc_rules : fc_rule
patterns : pattern
patterns_proper : pattern_proper
without_names : IDENTIFIER_TOK
'''
p[0] = [p[1]]
def p_empty_tuple(p):
''' bc_extras_opt :
data : LP_TOK RP_TOK
foreach_opt :
patterns_opt :
plan_extras_opt :
when_opt :
without_opt :
'''
p[0] = ()
def p_double_empty_tuple(p):
''' with_opt :
'''
p[0] = (), ()
def p_append_list(p):
''' assertions : assertions assertion
bc_premises : bc_premises inc_plan_vars bc_premise
bc_rules : bc_rules bc_rule
data_list : data_list ',' data
fc_premises : fc_premises fc_premise
fc_rules : fc_rules fc_rule
patterns : patterns ',' pattern
patterns_proper : patterns_proper ',' pattern
without_names : without_names ',' IDENTIFIER_TOK
'''
p[1].append(p[len(p)-1])
p[0] = p[1]
def p_pattern(p):
''' pattern : data '''
if goal_mode:
p[0] = pattern.pattern_literal(p[1])
else:
p[0] = "pattern.pattern_literal(%s)" % str(p[1])
def p_pattern_tuple1(p):
''' pattern_proper : LP_TOK '*' variable RP_TOK '''
if goal_mode:
p[0] = pattern.pattern_tuple((), p[3])
else:
p[0] = "pattern.pattern_tuple((), %s)" % p[3]
def p_pattern_tuple2(p):
''' pattern_proper : LP_TOK data_list ',' '*' variable RP_TOK '''
if goal_mode:
p[0] = pattern.pattern_tuple(
tuple(pattern.pattern_literal(x) for x in p[2]),
p[5])
else:
p[0] = "pattern.pattern_tuple((%s), %s)" % \
(' '.join("pattern.pattern_literal(%s)," % str(x)
for x in p[2]),
p[5])
def p_pattern_tuple3(p):
''' pattern_proper : LP_TOK data_list ',' patterns_proper rest_opt RP_TOK '''
if goal_mode:
p[0] = pattern.pattern_tuple(
tuple(itertools.chain(
(pattern.pattern_literal(x) for x in p[2]),
p[4])),
p[5])
else:
p[0] = "pattern.pattern_tuple((%s), %s)" % \
(' '.join(itertools.chain(
("pattern.pattern_literal(%s)," % str(x)
for x in p[2]),
(str(x) + ',' for x in p[4]))),
p[5])
def p_pattern_tuple4(p):
''' pattern_proper : LP_TOK patterns_proper rest_opt RP_TOK '''
if goal_mode:
p[0] = pattern.pattern_tuple(p[2], p[3])
else:
p[0] = "pattern.pattern_tuple((%s), %s)" % \
(' '.join(str(x) + ',' for x in p[2]),
p[3])
def p_tuple(p):
''' data : LP_TOK data_list comma_opt RP_TOK '''
if goal_mode:
p[0] = tuple(p[2])
else:
p[0] = '(' + ' '.join(str(x) + ',' for x in p[2]) + ')'
def p_error(t):
if t is None:
raise SyntaxError("invalid syntax", scanner.syntaxerror_params())
else:
raise SyntaxError("invalid syntax",
scanner.syntaxerror_params(t.lexpos, t.lineno))
parser = None
def init(this_module, check_tables = False, debug = 0):
global parser
if parser is None:
outputdir = os.path.dirname(this_module.__file__)
if debug:
parser = yacc.yacc(module=this_module, write_tables=0,
debug=debug, debugfile='krbparser.yacc.out',
outputdir=outputdir)
else:
if check_tables:
krbparser_mtime = os.path.getmtime(this_module.__file__)
tables_name = os.path.join(outputdir, 'krbparser_tables.py')
try:
ok = os.path.getmtime(tables_name) >= krbparser_mtime
except OSError:
ok = False
if not ok:
#print "regenerating krbparser_tables"
try: os.remove(tables_name)
except OSError: pass
try: os.remove(tables_name + 'c')
except OSError: pass
try: os.remove(tables_name + 'o')
except OSError: pass
parser = yacc.yacc(module=this_module, debug=0,
optimize=1, write_tables=1,
tabmodule='pyke.krb_compiler.krbparser_tables',
outputdir=outputdir)
# Use the first line for normal use, the second for testing changes in the
# grammer (the first line does not report grammer errors!).
def parse(this_module, filename, check_tables = False, debug = 0):
#def parse(this_module, filename, check_tables = True, debug = 1):
global goal_mode
init(this_module, check_tables, debug)
with open(filename) as f:
scanner.init(scanner, debug, check_tables)
scanner.lexer.lineno = 1
scanner.lexer.filename = filename
scanner.kfb_mode = False
scanner.goal_mode = False
goal_mode = False
#parser.restart()
return parser.parse(f.read() + '\n', lexer=scanner.lexer, tracking=True,
debug=debug)
def parse_goal(this_module, s, check_tables = False, debug = 0):
global goal_mode, pattern_vars
init(this_module, check_tables, debug)
scanner.init(scanner, debug, check_tables)
scanner.lexer.lineno = 1
scanner.lexer.filename = s
scanner.kfb_mode = False
scanner.goal_mode = True
goal_mode = True
pattern_vars = []
#parser.restart()
return parser.parse('check ' + s, lexer=scanner.lexer, tracking=True,
debug=debug)
def run(this_module, filename='TEST/krbparse_test.krb'):
r""" Used for testing.
>>> import os, os.path
>>> from pyke.krb_compiler import krbparser
>>> run(krbparser, os.path.join(os.path.dirname(__file__),
... 'TEST/krbparse_test.krb'))
('file',
None,
((('fc_rule',
'name1',
(('fc_premise',
'a',
'b',
("pattern.pattern_literal('x')", "contexts.variable('b')"),
7,
7),),
(('assert', 'c', 'd', ("contexts.variable('b')",), 9, 9),)),),
()),
((('bc_rule',
'name2',
('goal',
'x',
('pattern.pattern_literal(1)',
"contexts.variable('c')",
"pattern.pattern_literal((1, 'b',))",
"pattern.pattern_tuple((pattern.pattern_literal(1), pattern.pattern_literal('b'), contexts.variable('c'),), None)"),
(' (a, b, c)',),
12,
12),
(('bc_premise',
False,
"'a'",
"'b'",
("pattern.pattern_literal('x')", "contexts.variable('c')"),
('plan_spec',
None,
'plan#1',
('line1', "line2 (context['d']) end2"),
('d',),
15,
219),
14,
14),
('bc_premise',
False,
None,
"'x'",
('pattern.pattern_literal(1)',
'pattern.pattern_literal(2)',
'pattern.pattern_literal(3)'),
('plan_spec',
None,
'plan#2',
("some (context['plan'])(stuff) \\",
' and more stuff fail here'),
('plan',),
18,
280),
17,
17)),
("a (context['plan']) b",),
('plan',)),
('bc_rule',
'name3',
('goal',
'x',
('pattern.pattern_literal(1)',
"contexts.variable('c')",
"pattern.pattern_literal((1, 'b',))",
"pattern.pattern_tuple((pattern.pattern_literal(1), pattern.pattern_literal('b'), contexts.variable('c'),), None)"),
(),
24,
24),
(('bc_premise',
False,
"'a'",
"'b'",
("pattern.pattern_literal('x')", "contexts.variable('c')"),
('plan_spec',
None,
'plan#1',
('line1', "line2 (context['d']) end2"),
('d',),
27,
452),
26,
26),
('bc_premise',
False,
None,
"'x'",
('pattern.pattern_literal(1)',
'pattern.pattern_literal(2)',
'pattern.pattern_literal(3)'),
('as', 'foo_fn'),
29,
29)),
(),
())),
(),
()))
"""
import pprint
pprint.pprint(parse(this_module, filename, True))
|