Changeset 106:3ed5f8f4f9fc
- Timestamp:
- 02/20/10 14:33:55 (7 months ago)
- Author:
- Roger Gammans <rgammans@…>
- Branch:
- right-recursive-macro-grammar
- Message:
-
A right-recursive version of our grammar which allows Expr to used as literals.
In my opinion at the moment this is a dead-end , as the grammar is
ambigous with the extensions to the query op to allow expression
in all places. Additionally I don't think this ambiguity wins us
anything in practice as I can't imagine where we would use it.
However I'm committed it as a dead-head in case it becomes usefiul
later
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
r105
|
r106
|
|
| 2 | 2 | |
| 3 | 3 | ###Grammar stuff |
| 4 | | from pyparsing import Regex,Optional,ZeroOrMore, QuotedString , Literal, Word, alphas , nums , printables , CharsNotIn , stringEnd |
| | 4 | from pyparsing import Group, Forward,Regex,Optional,ZeroOrMore, QuotedString , Literal, Word, alphas , nums , CharsNotIn , stringEnd |
| 5 | 5 | from functools import partial |
| 6 | 6 | |
| … |
… |
|
| 26 | 26 | |
| 27 | 27 | ExprLimit = Regex("[^ \n\t]*[ \n\t]") |
| 28 | | Value = QuotedString('"') |
| | 28 | LiteralVal = QuotedString('"') |
| | 29 | |
| | 30 | def outparseState(s,loc,toks): |
| | 31 | print s,loc,toks |
| | 32 | return toks |
| | 33 | |
| | 34 | class BoolPartVal: |
| | 35 | """ |
| | 36 | Store the left hand part of a bool expr for later evalation. |
| | 37 | """ |
| | 38 | def __init__(self,op,value,*args): |
| | 39 | self.opsense = (op == "!=") |
| | 40 | self.value = value |
| | 41 | |
| | 42 | def cmp(self,ovalue): |
| | 43 | return self.opsense ^ (self.value == ovalue) |
| | 44 | |
| | 45 | |
| | 46 | class QueryExprVal: |
| | 47 | """ |
| | 48 | Store the left hand part of a query expr for later evalution. |
| | 49 | """ |
| | 50 | def __init__(self,boolpart,query,tval,seperator,fval,*args): |
| | 51 | self.boolpart = boolpart |
| | 52 | self.tval = tval |
| | 53 | self.fval = fval |
| | 54 | assert(query == "?") |
| | 55 | assert(seperator == "/") |
| | 56 | |
| | 57 | def eval(self,oval): |
| | 58 | if self.boolpart.cmp(oval): |
| | 59 | return self.tval |
| | 60 | else: return self.fval |
| | 61 | |
| | 62 | def EvalExpr(s,loc,toks): |
| | 63 | """ |
| | 64 | Walk down a list of query expression resovling them as we go |
| | 65 | """ |
| | 66 | c=toks[0] |
| | 67 | for q in toks[1:]: |
| | 68 | c=q.eval(c) |
| | 69 | return c |
| | 70 | |
| | 71 | |
| | 72 | def getField(s,loc,toks): |
| | 73 | modlogger.debug( "getField(%s)\n" % toks) |
| | 74 | field=toks[2] |
| | 75 | obj=toks[0] |
| | 76 | return obj[field] |
| 29 | 77 | |
| 30 | 78 | |
| … |
… |
|
| 36 | 84 | |
| 37 | 85 | NamedField = ObjectUID + seperator +fieldName |
| 38 | | ExprField = ObjectUID ^ \ |
| 39 | | NamedField |
| 40 | 86 | |
| 41 | | BoolExpr = ExprField + cfoperator + Value.copy() |
| 42 | | QueryExpr = BoolExpr + queryOp + Value.copy() + "/" +Value.copy() |
| | 87 | LValue = Forward() |
| 43 | 88 | |
| 44 | | ExprText = ExprField ^ \ |
| 45 | | QueryExpr |
| | 89 | ExprField = ObjectUID ^ \ |
| | 90 | NamedField |
| 46 | 91 | |
| 47 | | #Error = openExpr + ExprLimit |
| | 92 | #""" |
| 48 | 93 | |
| 49 | | #These production are about handling expressions |
| 50 | | # in run of text. The use is mainly historical. |
| 51 | | Expr = openExpr + ExprText + closeExpr |
| | 94 | LToken = LiteralVal ^ \ |
| | 95 | ExprField |
| 52 | 96 | |
| 53 | | textEle = NonExpr ^ \ |
| 54 | | Expr |
| 55 | | |
| 56 | | text = ZeroOrMore(textEle) |
| | 97 | BoolPart = cfoperator + LValue.copy() |
| | 98 | QueryExpr = BoolPart + queryOp + LValue.copy() + "/" + LValue.copy() |
| | 99 | ExprText = LToken + ZeroOrMore(QueryExpr) |
| | 100 | LValue << ( ExprText ^ LToken ) |
| 57 | 101 | |
| 58 | 102 | |
| | 103 | BoolPart.setParseAction(lambda s,loc,toks:BoolPartVal(*toks)) |
| | 104 | QueryExpr.setParseAction(lambda s,loc,toks:QueryExprVal(*toks)) |
| | 105 | ExprText.setParseAction(EvalExpr) |
| 59 | 106 | ## Functions for parsing. |
| 60 | | |
| 61 | | def getField(s,loc,toks): |
| 62 | | modlogger.debug( "getField(%s)\n" % toks) |
| 63 | | field=toks[2] |
| 64 | | obj=toks[0] |
| 65 | | return obj[field] |
| 66 | | |
| 67 | | |
| 68 | | def doBool(s,loc,toks): |
| 69 | | modlogger.debug( "getbol\n") |
| 70 | | sense=(toks[1]=="!=") |
| 71 | | return sense ^ ( str(toks[0]) == toks[2]) |
| 72 | | |
| 73 | | |
| 74 | | def doQuery(s,loc,toks): |
| 75 | | modlogger.debug( "doing query\n") |
| 76 | | if toks[0]: |
| 77 | | return toks[2] |
| 78 | | else: |
| 79 | | return toks[4] |
| 80 | 107 | |
| 81 | 108 | def initFromParse(s,loc,toks): |
| … |
… |
|
| 86 | 113 | else: return home.get_root().get_object(toks[0],toks[2]) |
| 87 | 114 | |
| 88 | | #def gotError(s,loc,toks): |
| 89 | | # sys.stderr.write("BARR") |
| 90 | | |
| 91 | | ## Bind functions to parse actions |
| 92 | 115 | |
| 93 | 116 | NamedField.setParseAction(getField) |
| 94 | | |
| 95 | | BoolExpr.setParseAction(doBool) |
| 96 | | QueryExpr.setParseAction(doQuery) |
| 97 | | Expr.setParseAction(lambda s,loc,tok:tok[1]) |
| 98 | | #Error.setParseAction(gotError) |
| 99 | | |
| 100 | 117 | ObjectUID.setParseAction(initFromParse) |
| 101 | 118 | |
| | 119 | ExprText.enablePackrat() |
| | 120 | ExprText.validate() |
| 102 | 121 | return ExprText + stringEnd |
| | 122 | |
| | 123 | |
| | 124 | if __name__ == "__main__": |
| | 125 | f = Grammar(None) |
| | 126 | print f.parseString(":name=\"X\"?\"Y\"/\"Z\"") |
| | 127 | #This is ambigous the second query could be have he first as it paramater |
| | 128 | # or be inside he final element of the first. |
| | 129 | print f.parseString(":name=\"X\"?\"Y\"/\"Z\"=\"Z\"?\"R\"/\"S\"") |
-
|
r105
|
r106
|
|
| 19 | 19 | # |
| 20 | 20 | """ |
| 21 | | Tests for the MysteryMachine.VersionNr class |
| | 21 | Tests for the MysteryMachine.parsetools.gramar file |
| 22 | 22 | """ |
| 23 | 23 | |
| 24 | | from MysteryMachine import * |
| 25 | 24 | from MysteryMachine.parsetools.grammar import Grammar |
| 26 | 25 | |
| … |
… |
|
| 61 | 60 | class GraamarTest(unittest.TestCase): |
| 62 | 61 | def setUp(self): |
| 63 | | StartApp(["--cfgengine=ConfigDict", "--cfgfile=test.cfg", "--testmode"]) |
| 64 | | self.parserA=Grammar( ObjectProxy( name="TestName", title="A Title") ) |
| | 62 | self.A = ( ObjectProxy( name="TestName", title="A Title", yes="YEAH!", no="Nope") ) |
| | 63 | self.parserA=Grammar( self.A ) |
| 65 | 64 | self.parserB=Grammar( ObjectProxy( name="WrongName", title="A Title") ) |
| 66 | 65 | |
| … |
… |
|
| 92 | 91 | self.assertEqual(helper(self.parserA,":name=\"TestName\"?\"Yes\"/\"No\""),"Yes") |
| 93 | 92 | self.assertEqual(helper(self.parserA,":name=\"WrongName\"?\":Yes\"/\"No\""),"No") |
| | 93 | #Now check with different lvalues.. |
| | 94 | self.assertEqual(helper(self.parserA,":name=\"TestName\"?:yes/:no"),"YEAH!") |
| | 95 | self.assertEqual(helper(self.parserA,":name=\"WrongName\"?:yes/:no"),"Nope") |
| | 96 | self.assertEqual(helper(self.parserA,":name=:title?:yes/:no"),"Nope") |
| | 97 | #Check Not equals |
| | 98 | self.assertEqual(helper(self.parserA,":name!=\"WrongName\"?:yes/:no"),"YEAH!") |
| | 99 | |
| 94 | 100 | |
| 95 | 101 | # Test handling of parse errors. |