Franck Pommereau

replaced tatsu with fastidious

#find zinc -name "*.lark" | while read LARK
#do
# TARGET=$(dirname $LARK)/$(basename $LARK .lark)parse.py
# if test "$LARK" -nt "$TARGET"
# then
# echo "### $LARK"
# python -m lark.tools.standalone "$LARK" > "$TARGET"
# else
# echo "... $LARK"
# fi
#done
find zinc -name "*.ebnf" | while read EBNF
do
TARGET=$(dirname $EBNF)/$(basename $EBNF .ebnf)parse.py
......@@ -9,3 +21,17 @@ do
echo "... $EBNF"
fi
done
find zinc -name "*_peg.py" | while read PEG
do
TARGET=$(dirname $PEG)/$(basename $PEG _peg.py)parse.py
CNAME=$(grep 'class.*(fastidious\.Parser)' "$PEG" | awk '{print $2}')
CPATH=$(realpath $PEG | sed -e "s|$(pwd)/*\(.*\).py|\\1|" -e "s|/|.|g")
if test "$PEG" -nt "$TARGET" || ! test -f "$TARGET"
then
echo "### $PEG ($CPATH.$CNAME)"
fastidious generate -o $TARGET $CPATH.$CNAME
else
echo "... $PEG ($CPATH.$CNAME)"
fi
done
......
......@@ -14,5 +14,5 @@ class ParseError (ZINCError) :
def __init__ (self, msg, lno=None, cno=None, path=None) :
loc = ":".join(str(p) for p in (path, lno, cno) if p is not None)
if loc :
msg = "%s: %s" % (loc, msg)
msg = "[%s] %s" % (loc, msg)
ZINCError.__init__(self, msg)
......
# coding: utf-8
import io, re
##
## insert INDENT/DEDENT
##
_indent = re.compile(r"^\s*")
def indedent (text, indent="↦", dedent="↤") :
"insert INDENT/DEDENT tokens into text"
stack = [0]
src = io.StringIO(text.rstrip() + "\n")
out = io.StringIO()
for i, line in enumerate(src) :
if line.rstrip() :
width = _indent.match(line).end()
if width > stack[-1] :
out.write(indent)
stack.append(width)
elif width < stack[-1] :
while width < stack[-1] :
out.write(dedent)
stack.pop()
if width != stack[-1] :
raise IndentationError("line %s" % (i+1))
out.write(line)
while stack[-1] > 0 :
out.write(dedent)
stack.pop()
return out.getvalue()
......
@@grammar :: zn
@@eol_comments :: /#.*?$/
@@whitespace :: /[\t ]+/
spec =
{nl}
"lang" lang:text nl
declare:{decl}
"net" net:text ":" nl
nodes:{trans|place}+
{nl}$
;
decl =
{nl} "declare" ['@' level:text] source:text nl
;
place =
{nl} "place" name:text [type:placetype] ["=" tokens:(","%{ token }+)] nl
;
placetype =
| tuple:placetuple
| text:text
;
placetuple =
"(" ","%{ placetuple | text }+ ")"
;
token =
| number:number
| text:text
;
trans =
{nl} "trans" name:text [guard:/[^:]+/] ":" nl
arcs:{arc}+
;
arc =
{nl} way:("<" | ">") place:text [mod:arcmod] kind:arckind "=" label:tail nl
;
arckind = "val" | "var" | "expr" | "flush+" | "flush" | "fill" | tuple
;
arcmod =
| kind:"?"
| kind:"!" [guard:code]
;
tuple =
"(" ","%{ tuple | text | number }+ ")"
;
tailtuple =
tuple $
;
tail =
/.*?$/
;
number =
/[+-]?[0-9]+/
;
nl =
/\s*[\n\r]\s*/
;
text =
| code:code
| name:name
| string:string
;
code =
| '{' CODEC '}'
| '[' CODEB ']'
;
CODEC =
{ /([^{}]|\\[{}])*/ | CODEC }
;
CODEB =
{ /([^\[\]]|\\[\[\]])*/ | CODEB }
;
name =
/[a-zA-Z_][a-zA-Z0-9_]*/
;
string =
| "'''" { /[^'\\]+/ | "''" !"'" | "'" !"'" | /\\(.|\n)/ } "'''"
| '"""' { /[^"\\]+/ | '""' !'"' | '"' !'"' | /\\(.|\n)/ } '"""'
| "'" { "\\" /./ | /[^\\\r\n\f']+/ } "'"
| '"' { "\\" /./ | /[^\\\r\n\f"]+/ } '"'
;
import ast, collections, functools
import ast, functools
from zinc import nets, ParseError, ZINCError
from zinc.io import znparse
from zinc.data import flatten
from .. import nets, ParseError, ZINCError
from . import znparse, indedent
from ..data import flatten
class TupleParser (object) :
class _TupleParser (object) :
def __init__ (self) :
self.p = znparse.znParser()
def parse (self, source) :
......@@ -30,16 +30,7 @@ class TupleParser (object) :
elif st.code :
return st.code
class Parser (TupleParser) :
def __init__ (self, module=nets) :
self.n = module
self.p = znparse.znParser()
self.t = TupleParser()
def parse (self, source, path) :
self._s = source.rstrip() + "\n"
self._p = path
self._l = {}
return self.p.parse(self._s, "spec", semantics=self)
class _Parser (_TupleParser) :
def spec (self, st) :
try :
net = self.n.PetriNet(st.net, st.lang)
......@@ -76,44 +67,6 @@ class Parser (TupleParser) :
except ZINCError as err :
raise ParseError(err, self._l[node.name, place], None, self._p)
return net
def decl (self, st) :
return st.level, st.source
def place (self, st) :
return (self.n.Place(st.name, (st.tokens or [])[::2], st.type),
st.parseinfo.line+1)
def placetype (self, st) :
if st.text :
return st.text
elif st.tuple :
return st.tuple
def placetuple (self, st) :
def mktuple (content) :
if isinstance(content, list) :
return tuple(mktuple(c) for c in content[1][::2])
else :
return content
return mktuple(st)
def token (self, st) :
if st.number :
return self.n.Token(st.number)
elif st.text :
return self.n.Token(st.text)
def trans (self, st) :
inputs, outputs = collections.defaultdict(list), collections.defaultdict(list)
for isin, place, label, lineno in st.arcs :
if isin :
inputs[place].append(label)
self._l[place, st.name] = lineno
else :
outputs[place].append(label)
self._l[st.name, place] = lineno
return (self.n.Transition(st.name, st.guard.strip()),
st.parseinfo.line+1, inputs, outputs)
def guard (self, st) :
if st.text :
return st.text
elif st.raw :
return st.raw
def _mkarc (self, st) :
_arc = {"val" : self.n.Value,
"var" : self.n.Variable,
......@@ -149,6 +102,22 @@ class Parser (TupleParser) :
except ZINCError as err :
raise ParseError(str(err), st.parseinfo.line+1, None, self._p)
class Parser (object) :
def __init__ (self, module=nets) :
self.n = module
def parse (self, source, path) :
parser = znparse.ZnParser(indedent(source))
parser.n = self.n
try :
result = parser.INPUT()
if result is parser.NoMatch or parser.p_peek() is not None:
parser.p_raise()
return result
except parser.ParserError as err :
raise
except :
raise
def loads (source, module=nets) :
return Parser(module).parse(source, "<string>")
......
# coding: utf-8
from .. import ZINCError
import ast, collections, functools
import fastidious
class ZnParser (fastidious.Parser) :
__default__ = "INPUT"
__grammar__ = r"""
INPUT <- NL? :spec {@spec}
NL <- ~"([\t ]*(#.*)?\n)+" {_drop}
_ <- ~"[\t ]+"? {_drop}
TAIL <- ~".+" {p_flatten}
COLON <- _ ":" _ {_drop}
COMMA <- _ "," _ {p_flatten}
AT <- _ "@" _ {p_flatten}
EQ <- _ "=" _ {p_flatten}
LT <- _ "<" _ {p_flatten}
GT <- _ ">" _ {p_flatten}
LP <- _ "(" _ {p_flatten}
RP <- _ ")" _ {p_flatten}
LSB <- _ "[" _ {p_flatten}
RSB <- _ "]" _ {p_flatten}
LCB <- _ "{" _ {p_flatten}
RCB <- _ "}" _ {p_flatten}
INDENT <- _ "↦" NL? _ {_drop}
DEDENT <- _ "↤" NL? _ {_drop}
LANG <- _ "lang" _ {p_flatten}
NET <- _ "net" _ {p_flatten}
PLACE <- _ "place" _ {p_flatten}
TRANS <- _ "trans" _ {p_flatten}
VAL <- _ "val" _ {p_flatten}
VAR <- _ "var" _ {p_flatten}
EXPR <- _ "expr" _ {p_flatten}
DECLARE <- _ "declare" _ {p_flatten}
FLUSHPLUS <- _ "flush+" _ {p_flatten}
FLUSH <- _ "flush" _ {p_flatten}
FILL <- _ "fill" _ {p_flatten}
TEST <- _ "?" _ {p_flatten}
BANG <- _ "!" _ {p_flatten}
NUMBER <- _ ~"[+-]?[0-9]+" {_number}
NAME <- _ ~"[a-z][a-z0-9_]*"i _ {p_flatten}
text <- name:NAME / :code / :string {_first}
code <- codec / codeb {_code}
codec <- LCB (~"([^{}\\\\]|\\[{}])+" / codec)* RCB {p_flatten}
codeb <- LSB (~"([^\\[\\]\\\\]|\\[\\[\\]])+" / codeb)* RSB {p_flatten}
string <- _ ( ~"'{3}.*?'{3}"s
/ ~'"{3}.*?"{3}'s
/ ~"'([^'\\\\]|\\.)*'"
/ ~'"([^"\\\\]|\\.)*"' ) _ {_string}
"""
def _drop (self, match) :
return ""
def _number (self, match) :
return int(self.p_flatten(match))
def _code (self, match) :
return (self.p_flatten(match).strip()[1:-1])
def _string (self, match) :
return ast.literal_eval(self.p_flatten(match).strip())
def _tuple (self, match) :
"""callback to transform matched comma-separated tuples
<- item (COMMA item)*
=> (item, ...)
"""
lst = []
for m in match :
if isinstance(m, list) :
lst.extend(i[1] for i in m)
else :
lst.append(m)
return tuple(lst)
def _tuple1 (self, match) :
"""callback to transform matched comma-separated tuples
<- DELIM item (COMMA item)* DELIM
=> (item, ...)
"""
lst = []
for m in match[1:-1] :
if isinstance(m, list) :
lst.extend(i[1] for i in m)
else :
lst.append(m)
return tuple(lst)
def _first (self, match, **args) :
for k, v in args.items() :
if v is not self.NoMatch :
return v
return self.NoMatch
__grammar__ += r"""
spec <- LANG lang:text NL
declare:decl*
NET net:text COLON NL INDENT nodes:(place / trans)+ DEDENT
"""
def on_spec (self, match, lang, declare, net, nodes) :
try :
net = self.n.PetriNet(net, lang)
except ZINCError as err :
self.p_parse_error(str(err))
for lvl, decl in declare :
net.declare(decl, lvl)
for pos, node, *rest in nodes :
if isinstance(node, self.n.Place) :
try :
net.add_place(node)
except ZINCError as err :
self.p_parse_error(str(err), pos)
else :
try :
net.add_transition(node)
except ZINCError as err :
self.p_parse_error(str(err), pos)
for arcs, add in zip(rest, (net.add_input, net.add_output)) :
for place, arc in arcs.items() :
try :
pos, label = arc[0]
if len(arc) == 1 :
add(place, node.name, label)
else :
add(place, node.name,
self.n.MultiArc(*(lbl for _, lbl in arc)))
except ZINCError as err :
self.p_parse_error(str(err), pos)
return net
__grammar__ += r"""
decl <- DECLARE (AT level:text)? source:text NL
"""
def on_decl (self, match, source, level=None) :
return level, source
__grammar__ += r"""
place <- PLACE name:text type:placetype? (EQ tokens:tokens)? NL
placetype <- :text / :placetuple {_first}
placetuple <- LP placeitem (COMMA placeitem)* RP {_tuple1}
placeitem <- :text / :placetuple {_first}
tokens <- tok (COMMA tok)* {_tuple}
tok <- number:NUMBER / :text {_first}
"""
def on_place (self, match, name, type=None, tokens=[]) :
return self.pos, self.n.Place(name, tokens, type)
__grammar__ += r"""
trans <- TRANS name:text guard:(~"[^:]+")? COLON NL INDENT arcs:arc+ DEDENT
arc <- way:(LT / GT) place:text mod:arcmod? kind:arckind EQ label:TAIL NL
arckind <- VAL / VAR / EXPR / FLUSHPLUS / FLUSH / FILL / arctuple
arcmod <- kind:(TEST / BANG) guard:code?
arctuple <- LP arcitem (COMMA arcitem)* RP {_tuple1}
arcitem <- :text / number:NUMBER / :arctuple {_first}
"""
def on_trans (self, match, name, arcs, guard=None) :
inputs, outputs = collections.defaultdict(list), collections.defaultdict(list)
for pos, isin, place, label in arcs :
if isin :
inputs[place].append((pos, label))
else :
outputs[place].append((pos, label))
return self.pos, self.n.Transition(name, guard), inputs, outputs
def on_arc (self, match, way, place, kind, label, mod=None) :
return self.pos, way == "<", place, self._mkarc(kind, label, mod)
def _mkarc (self, kind, label, mod) :
_arc = {"val" : self.n.Value,
"var" : self.n.Variable,
"expr" : self.n.Expression,
"flush" : self.n.Flush,
"flush+" : functools.partial(self.n.Flush, notempty=True),
"fill" : self.n.Fill}
def mktuple (kind, label) :
if not isinstance(label, tuple) or len(kind) != len(label) :
self.p_parse_error("unmatched tuples %r and %r" % (kind, label))
return self.n.Tuple(*(mktuple(k, l) for k, l in zip(kind, label)))
if isinstance(kind, tuple) :
lbl = self.p_parse(label, "arctuple")
label = mktuple(kind, lbl)
elif kind in _arc :
label = _arc[kind](label.strip())
if mod :
mod_kind, mod_guard = mod
if mod_kind == "?" :
label = self.n.Test(label)
elif mod_kind == "!" :
label = self.n.Inhibitor(label, mod_guard)
return label
def on_arcmod (self, match, kind, guard=None) :
return kind, guard
This diff could not be displayed because it is too large.