Commit d4d32ac0 authored by VIGNET Pierre's avatar VIGNET Pierre
Browse files

Proper encapsulation of project => ready to separate GUI and library; Add...

Proper encapsulation of project => ready to separate GUI and library; Add logger on MCLQuery & chart_checker_controler
parent b5f2efed
CMD_PYTHON=python2
PYTHON=$(CMD_PYTHON) -m cadbiom
#LOGLEVEL=--loglevel=debug
#LOGLEVEL=--loglevel=info
COMMAND=$(PYTHON) $(LOGLEVEL)
.PHONY: all
all: build
......@@ -9,3 +15,16 @@ build:
.PHONY: run
run:
python cadbiom_des.py
.PHONY: run_gui
run_gui:
@echo Launch GUI
$(COMMAND) run_gui
unit_test:
@echo Unit tests...
./mac.sh
py.test
version:
$(COMMAND) --version
# -*- coding: utf-8 -*-
"""
Created on Nov 2016
..sectionauthor:: Pierre.VIGNET <pierre.vignet@inria.fr>
"""
# Standard imports
import argparse
import os
# Custom imports
from cadbiom import commons
from cadbiom.info import PACKAGE_VERSION
LOGGER = commons.logger()
def run_gui(args):
"""Launch Cadbiom gui"""
import gtk
from cadbiom.gt_gui.charter import Charter
charter = Charter(None)
charter.show()
gtk.main()
def args_to_param(args):
"""Return argparse namespace as a dict {variable name: value}"""
return {k: v for k, v in vars(args).items() if k != 'func'}
class readable_dir(argparse.Action):
"""
http://stackoverflow.com/questions/11415570/directory-path-types-with-argparse
"""
def __call__(self, parser, namespace, values, option_string=None):
prospective_dir = values
if not os.path.isdir(prospective_dir):
raise argparse.ArgumentTypeError(
"readable_dir:{0} is not a valid path".format(prospective_dir))
if os.access(prospective_dir, os.R_OK):
setattr(namespace, self.dest, prospective_dir)
else:
raise argparse.ArgumentTypeError(
"readable_dir:{0} is not a readable dir".format(prospective_dir))
if __name__ == '__main__':
# parser configuration
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-v', '--version', action='version',
version='%(prog)s ' + PACKAGE_VERSION)
subparsers = parser.add_subparsers(title='subcommands')
# subparser: launch GUI
parser_input_file = subparsers.add_parser('run_gui',
help=run_gui.__doc__, )
parser_input_file.set_defaults(func=run_gui)
# get program args and launch associated command
args = parser.parse_args()
args.func(args)
......@@ -29,8 +29,8 @@
# end[licence]
import socket
from antlr3 import Parser, TokenStream, RecognitionException, Token
from antlr3.tree import CommonTreeAdaptor, TreeAdaptor, Tree
from cadbiom.antlr3 import Parser, TokenStream, RecognitionException, Token
from cadbiom.antlr3.tree import CommonTreeAdaptor, TreeAdaptor, Tree
class DebugParser(Parser):
def __init__(self, stream, state=None, dbg=None, *args, **kwargs):
......@@ -47,9 +47,9 @@ class DebugParser(Parser):
def setDebugListener(self, dbg):
"""Provide a new debug event listener for this parser. Notify the
"""Provide a new debug event listener for this parser. Notify the
input stream too that it should send events to this listener.
"""
"""
if hasattr(self.input, 'dbg'):
self.input.dbg = dbg
......@@ -128,7 +128,7 @@ class DebugTokenStream(TokenStream):
def consumeInitialHiddenTokens(self):
"""consume all initial off-channel tokens"""
firstOnChannelTokenIndex = self.input.index()
for idx in range(firstOnChannelTokenIndex):
self._dbg.consumeHiddenToken(self.input.get(idx))
......@@ -256,7 +256,7 @@ class DebugTreeAdaptor(TreeAdaptor):
def simulateTreeConstruction(self, t):
"""^(A B C): emit create A, create B, add child, ..."""
"""^(A B C): emit create A, create B, add child, ..."""
self.dbg.createNode(t)
for i in range(self.adaptor.getChildCount(t)):
child = self.adaptor.getChild(t, i)
......@@ -399,7 +399,7 @@ class DebugTreeAdaptor(TreeAdaptor):
class DebugEventListener(object):
"""All debugging events that a recognizer can trigger.
I did not create a separate AST debugging interface as it would create
lots of extra classes and DebugParser has a dbg var defined, which makes
it hard to change to ASTDebugEventListener. I looked hard at this issue
......@@ -412,7 +412,7 @@ class DebugEventListener(object):
PROTOCOL_VERSION = "2"
def enterRule(self, grammarFileName, ruleName):
"""The parser has just entered a rule. No decision has been made about
"""The parser has just entered a rule. No decision has been made about
which alt is predicted. This is fired AFTER init actions have been
executed. Attributes are defined and available etc...
The grammarFileName allows composite grammars to jump around among
......@@ -423,25 +423,25 @@ class DebugEventListener(object):
def enterAlt(self, alt):
"""Because rules can have lots of alternatives, it is very useful to
"""Because rules can have lots of alternatives, it is very useful to
know which alt you are entering. This is 1..n for n alts.
"""
pass
def exitRule(self, grammarFileName, ruleName):
"""This is the last thing executed before leaving a rule. It is
"""This is the last thing executed before leaving a rule. It is
executed even if an exception is thrown. This is triggered after
error reporting and recovery have occurred (unless the exception is
not caught in this rule). This implies an "exitAlt" event.
The grammarFileName allows composite grammars to jump around among
multiple grammar files.
"""
"""
pass
def enterSubRule(self, decisionNumber):
"""Track entry into any (...) subrule other EBNF construct"""
"""Track entry into any (...) subrule other EBNF construct"""
pass
......@@ -450,7 +450,7 @@ class DebugEventListener(object):
def enterDecision(self, decisionNumber):
"""Every decision, fixed k or arbitrary, has an enter/exit event
"""Every decision, fixed k or arbitrary, has an enter/exit event
so that a GUI can easily track what LT/consume events are
associated with prediction. You will see a single enter/exit
subrule but multiple enter/exit decision events, one for each
......@@ -464,40 +464,40 @@ class DebugEventListener(object):
def consumeToken(self, t):
"""An input token was consumed; matched by any kind of element.
"""An input token was consumed; matched by any kind of element.
Trigger after the token was matched by things like match(), matchAny().
"""
"""
pass
def consumeHiddenToken(self, t):
"""An off-channel input token was consumed.
"""An off-channel input token was consumed.
Trigger after the token was matched by things like match(), matchAny().
(unless of course the hidden token is first stuff in the input stream).
"""
"""
pass
def LT(self, i, t):
"""Somebody (anybody) looked ahead. Note that this actually gets
"""Somebody (anybody) looked ahead. Note that this actually gets
triggered by both LA and LT calls. The debugger will want to know
which Token object was examined. Like consumeToken, this indicates
what token was seen at that depth. A remote debugger cannot look
ahead into a file it doesn't have so LT events must pass the token
even if the info is redundant.
"""
"""
pass
def mark(self, marker):
"""The parser is going to look arbitrarily ahead; mark this location,
"""The parser is going to look arbitrarily ahead; mark this location,
the token stream's marker is sent in case you need it.
"""
"""
pass
def rewind(self, marker=None):
"""After an arbitrairly long lookahead as with a cyclic DFA (or with
"""After an arbitrairly long lookahead as with a cyclic DFA (or with
any backtrack), this informs the debugger that stream should be
rewound to the position associated with marker.
......@@ -514,19 +514,19 @@ class DebugEventListener(object):
def location(self, line, pos):
"""To watch a parser move through the grammar, the parser needs to
"""To watch a parser move through the grammar, the parser needs to
inform the debugger what line/charPos it is passing in the grammar.
For now, this does not know how to switch from one grammar to the
other and back for island grammars etc...
This should also allow breakpoints because the debugger can stop
the parser whenever it hits this line/pos.
"""
"""
pass
def recognitionException(self, e):
"""A recognition exception occurred such as NoViableAltException. I made
"""A recognition exception occurred such as NoViableAltException. I made
this a generic event so that I can alter the exception hierachy later
without having to alter all the debug objects.
......@@ -554,70 +554,70 @@ class DebugEventListener(object):
The sequence for this rule (with no viable alt in the subrule) for
input 'c c' (there are 3 tokens) is:
commence
LT(1)
enterRule b
location 7 1
enter decision 3
LT(1)
exit decision 3
enterAlt1
location 7 5
LT(1)
consumeToken [c/<4>,1:0]
location 7 7
enterSubRule 2
enter decision 2
LT(1)
LT(1)
recognitionException NoViableAltException 2 1 2
exit decision 2
exitSubRule 2
beginResync
LT(1)
consumeToken [c/<4>,1:1]
LT(1)
endResync
LT(-1)
exitRule b
terminate
"""
commence
LT(1)
enterRule b
location 7 1
enter decision 3
LT(1)
exit decision 3
enterAlt1
location 7 5
LT(1)
consumeToken [c/<4>,1:0]
location 7 7
enterSubRule 2
enter decision 2
LT(1)
LT(1)
recognitionException NoViableAltException 2 1 2
exit decision 2
exitSubRule 2
beginResync
LT(1)
consumeToken [c/<4>,1:1]
LT(1)
endResync
LT(-1)
exitRule b
terminate
"""
pass
def beginResync(self):
"""Indicates the recognizer is about to consume tokens to resynchronize
"""Indicates the recognizer is about to consume tokens to resynchronize
the parser. Any consume events from here until the recovered event
are not part of the parse--they are dead tokens.
"""
pass
def endResync(self):
"""Indicates that the recognizer has finished consuming tokens in order
"""Indicates that the recognizer has finished consuming tokens in order
to resychronize. There may be multiple beginResync/endResync pairs
before the recognizer comes out of errorRecovery mode (in which
multiple errors are suppressed). This will be useful
in a gui where you want to probably grey out tokens that are consumed
but not matched to anything in grammar. Anything between
a beginResync/endResync pair was tossed out by the parser.
"""
"""
pass
def semanticPredicate(self, result, predicate):
"""A semantic predicate was evaluate with this result and action text"""
"""A semantic predicate was evaluate with this result and action text"""
pass
def commence(self):
"""Announce that parsing has begun. Not technically useful except for
"""Announce that parsing has begun. Not technically useful except for
sending events over a socket. A GUI for example will launch a thread
to connect and communicate with a remote parser. The thread will want
to notify the GUI when a connection is made. ANTLR parsers
trigger this upon entry to the first rule (the ruleLevel is used to
figure this out).
"""
"""
pass
......@@ -626,7 +626,7 @@ class DebugEventListener(object):
remote debugging listeners that it's time to quit. When the rule
invocation level goes to zero at the end of a rule, we are done
parsing.
"""
"""
pass
......@@ -645,10 +645,10 @@ class DebugEventListener(object):
def LT(self, i, t):
"""The tree parser lookedahead. If the type is UP or DOWN,
"""The tree parser lookedahead. If the type is UP or DOWN,
then the ID is not really meaningful as it's fixed--there is
just one UP node and one DOWN navigation node.
"""
"""
pass
......@@ -656,7 +656,7 @@ class DebugEventListener(object):
## A S T E v e n t s
def nilNode(self, t):
"""A nil was created (even nil nodes have a unique ID...
"""A nil was created (even nil nodes have a unique ID...
they are not "null" per se). As of 4/28/2006, this
seems to be uniquely triggered when starting a new subtree
such as when entering a subrule in automatic mode and when
......@@ -664,29 +664,29 @@ class DebugEventListener(object):
If you are receiving this event over a socket via
RemoteDebugEventSocketListener then only t.ID is set.
"""
"""
pass
def errorNode(self, t):
"""Upon syntax error, recognizers bracket the error with an error node
"""Upon syntax error, recognizers bracket the error with an error node
if they are building ASTs.
"""
pass
def createNode(self, node, token=None):
"""Announce a new node built from token elements such as type etc...
"""Announce a new node built from token elements such as type etc...
If you are receiving this event over a socket via
RemoteDebugEventSocketListener then only t.ID, type, text are
set.
"""
"""
pass
def becomeRoot(self, newRoot, oldRoot):
"""Make a node the new root of an existing root.
"""Make a node the new root of an existing root.
Note: the newRootID parameter is possibly different
than the TreeAdaptor.becomeRoot() newRoot parameter.
......@@ -701,12 +701,12 @@ class DebugEventListener(object):
RemoteDebugEventSocketListener then only IDs are set.
@see antlr3.tree.TreeAdaptor.becomeRoot()
"""
"""
pass
def addChild(self, root, child):
"""Make childID a child of rootID.
"""Make childID a child of rootID.
If you are receiving this event over a socket via
RemoteDebugEventSocketListener then only IDs are set.
......@@ -717,11 +717,11 @@ class DebugEventListener(object):
def setTokenBoundaries(self, t, tokenStartIndex, tokenStopIndex):
"""Set the token start/stop token index for a subtree root or node.
"""Set the token start/stop token index for a subtree root or node.
If you are receiving this event over a socket via
RemoteDebugEventSocketListener then only t.ID is set.
"""
"""
pass
......@@ -846,7 +846,7 @@ class DebugEventSocketProxy(DebugEventListener):
self.grammarFileName = recognizer.getGrammarFileName()
# Almost certainly the recognizer will have adaptor set, but
# Almost certainly the recognizer will have adaptor set, but
# we don't know how to cast it (Parser or TreeParser) to get
# the adaptor field. Must be set with a constructor. :(
self.adaptor = adaptor
......@@ -1061,7 +1061,7 @@ class DebugEventSocketProxy(DebugEventListener):
# buf.append(tokenIndex);
# serializeText(buf, text);
## A S T E v e n t s
def nilNode(self, t):
......
......@@ -30,8 +30,8 @@
#
# end[licensc]
from antlr3.constants import EOF
from antlr3.exceptions import NoViableAltException, BacktrackingFailed
from cadbiom.antlr3.constants import EOF
from cadbiom.antlr3.exceptions import NoViableAltException, BacktrackingFailed
class DFA(object):
......@@ -40,9 +40,9 @@ class DFA(object):
Any state that has a semantic predicate edge is special; those states
are generated with if-then-else structures in a specialStateTransition()
which is generated by cyclicDFA template.
"""
def __init__(
self,
recognizer, decisionNumber,
......@@ -64,16 +64,16 @@ class DFA(object):
def predict(self, input):
"""
From the input stream, predict what alternative will succeed
using this DFA (representing the covering regular approximation
to the underlying CFL). Return an alternative number 1..n. Throw
an exception upon error.
"""
using this DFA (representing the covering regular approximation
to the underlying CFL). Return an alternative number 1..n. Throw
an exception upon error.
"""
mark = input.mark()
s = 0 # we always start at s0
try:
for _ in xrange(50000):
#print "***Current state = %d" % s
specialState = self.special[s]
if specialState >= 0:
#print "is special"
......@@ -98,7 +98,7 @@ class DFA(object):
# move to next state
snext = self.transition[s][c-self.min[s]]
#print "in range, next state = %d" % snext
if snext < 0:
#print "not a normal transition"
# was in range but not a normal transition
......@@ -107,7 +107,7 @@ class DFA(object):
# state.
if self.eot[s] >= 0: # EOT Transition to accept state?
#print "EOT trans to accept state %d" % self.eot[s]
s = self.eot[s]
input.consume()
# TODO: I had this as return accept[eot[s]]
......@@ -127,7 +127,7 @@ class DFA(object):
if self.eot[s] >= 0:
#print "EOT to %d" % self.eot[s]
s = self.eot[s]
input.consume()
continue
......@@ -144,7 +144,7 @@ class DFA(object):
else:
raise RuntimeError("DFA bang!")
finally:
input.rewind(mark)
......@@ -195,9 +195,9 @@ class DFA(object):
15MB lexer, eating all my swap space and I was to impacient to see,
if it could finish at all. With packed initializers that are unpacked
at import time of the lexer module, everything works like a charm.
"""
ret = []
for i in range(len(string) / 2):
(n, v) = ord(string[i*2]), ord(string[i*2+1])
......@@ -209,5 +209,5 @@ class DFA(object):
ret += [v] * n
return ret
unpack = classmethod(unpack)
......@@ -38,7 +38,7 @@ This module contains all support classes for AST construction and tree parsers.
# lot's of docstrings are missing, don't complain for now...
# pylint: disable-msg=C0111
from antlr3.tree import CommonTreeAdaptor
from cadbiom.antlr3.tree import CommonTreeAdaptor
import stringtemplate3
class DOTTreeGenerator(object):
......@@ -114,7 +114,7 @@ class DOTTreeGenerator(object):
# for each child, do a "<unique-name> [label=text]" node def
for i in range(n):
child = adaptor.getChild(tree, i)
number = self.getNodeNumber(child)
if number not in knownNodes:
nodeST = self.getNodeST(adaptor, child)
......@@ -203,7 +203,7 @@ def toDOT(tree, adaptor=None, treeST=DOTTreeGenerator._treeST, edgeST=DOTTreeGen
print tree.toStringTree()
st = antlr3.extras.toDOT(t)
print st
"""
gen = DOTTreeGenerator()
......
......@@ -30,7 +30,7 @@
#
# end[licence]
from antlr3.constants import INVALID_TOKEN_TYPE
from cadbiom.antlr3.constants import INVALID_TOKEN_TYPE
class BacktrackingFailed(Exception):
......@@ -60,7 +60,7 @@ class RecognitionException(Exception):
want to quit upon first error, you can turn off the automatic error
handling mechanism using rulecatch action, but you still need to
override methods mismatch and recoverFromMismatchSet.
In general, the recognition exceptions can track where in a grammar a
problem occurred and/or what was the expected input. While the parser
knows its state (such as current input symbol and line info) that
......@@ -69,33 +69,33 @@ class RecognitionException(Exception):
perhaps print an entire line of input not just a single token, for example.
Better to just say the recognizer had a problem and then let the parser
figure out a fancy report.
"""