Re: [Pyparsing] need help building parsing framework for disability access tool
Brought to you by:
ptmcg
From: Eric S.. J. <es...@es...> - 2012-09-12 03:04:47
|
----- Original Message ----- > From: "Mario R. Osorio" <nim...@gm...> > To: "Eric S.. Johansson" <es...@es...> > Cc: "Paul McGuire" <pt...@au...>, > pyp...@li... > Sent: Tuesday, September 11, 2012 8:02:58 PM > Subject: Re: [Pyparsing] need help building parsing framework for > disability access tool > Eric > I am by no means what you would call an expert in language definition > nor python; I just had the need to use a parser for a "mini > language" that sure enough, turned into an almost full fledged one. > I tried about three solutions (all in python) and ended up using > pyparse and loving it! > I found a book on pyparse, whether it was free online or ... I'm not > sure. > a pointer to book would be great > Oh, and by the way; this tool and the book is written in a very > friendly "alien" dialect. Please restate your original question as I > missed your original post. I can send you some of my code if you > need. oh boy, friendly aliens. How would they say "take me to your leader"? --- here's the original example I gave. Below I've tried to expand and comment. [script [url /files/tw-sack.js]] [script [url /files/logic.js]] [script [url /files/ak_vacation.js]] [script [body onload="doSomething()"]] [title Out-of-Office E-mail Setup] [div [id wrapper] [heading [level 1] Out-of-Office E-mail Setup] [heading [level 2] User Account: [reveal active_user]] [span [class label]Please answer the following questions in order to complete the setup of your out-of-office mode. Please note that you must login and disable this mode once you return from vacation.] [comment preserve active user] [reveal administrative_instructions] [reveal administrative_incremental] [div [id account][class data][reveal administrative_display]] [reveal administrative_interface] [form [id account_data] [action edit_vacation] [method post] [hidden [id active_user][name active_user] [value [reveal active_user]]] [span [class label]I want the out-of-office notification:] [radio [class textentry] [name active_checked][rawbits onclick="javascript:showField('message');showField('exceptions');" ] [value on][checked [reveal enabled]]Enabled] [radio [class textentry] [name active_checked] [rawbits onclick="javascript:hideField('message');hideField('exceptions');"] [value off] [checked [reveal disabled [default off]]] Disabled] [div [id message] [class normal] [span [class label]Enter all of your e-mail addresses in this box, one address on a line] [div [class center] [textarea [reveal addresses] [class data] [name addresses] [rows 5] [columns 50] ]] [span [class label]I want the message to say:] [div [class center] [textarea [class data] [reveal_raw message] [name message] [rows 7] [columns 50] ]] [span[class label] once you've made changes to the above information, you must save it so it can take effect] ] [div [class center] [button [name commit] [class button] [value save] [type submit]] ] ]] ---------------- reference example explained -------------- [comment """each script command has a single argument. One of the interesting things about the existing implementation is that arguments for a command is defined as attributes of the parser/action code method. it looks like this: self.context_script = ["body", "URL", "page", "xfile"] the reason for the triple quotes around the comment is that I have special characters in the body of the comment. Normally a comment wouldn't need the protection of triple quotes and could just be plain text inside the body. the example below also shows how each component would be expanded below the owner of that component. I'll do this in several other places below. """ ] [script [url /files/tw-sack.js ] ] [script [url /files/logic.js]] [script [url /files/ak_vacation.js]] [script [body onload="doSomething()"]] [comment example of a simple command with data for the command immediately following the command and terminated by a close bracket] [title Out-of-Office E-mail Setup] [comment really need to rename div because while it is in the vocabulary of NaturallySpeaking, it's not really cognitively friendly. this is an example of a command with a single argument with a naked text value for the ID.] [div [id wrapper] [comment an example of command with a single argument and data following the argument] [heading [level 1] Out-of-Office E-mail Setup] [comment command with single argument and composite data consisting of text and results from another command. The order of execution needs to be revealed first then the composite data string is constructed. The argument is evaluated in a similar fashion because it could also be composite] [heading [level 2] User Account: [reveal active_user]] [comment same command as above but the argument is now generated from program data] [heading [level [reveal second_level ] ] User Account: [reveal active_user] ] ] [span [class label]Please answer the following questions in order to complete the setup of your out-of-office mode. Please note that you must login and disable this mode once you return from vacation.] [comment preserve active user] [comment the next two reveals actually inject akasha markup into the markup stream. Think in this case it's like a dynamic include except it's the program that hands the application data instead of the application getting the data from a file] [reveal administrative_instructions] [reveal administrative_incremental] [comment this is a good example of two arguments and reveal filling the data section.] [div [id account ] [class data ] [reveal administrative_display ] ] [reveal administrative_interface] [form [id account_data] [action edit_vacation] [method post] [hidden [id active_user][name active_user] [value [reveal active_user]]] [span [class label]I want the out-of-office notification:] [radio [class textentry] [name active_checked][rawbits onclick="javascript:showField('message');showField('exceptions');" ] [value on][checked [reveal enabled]]Enabled] [radio [class textentry] [name active_checked] [rawbits onclick="javascript:hideField('message');hideField('exceptions');"] [value off] [checked [reveal disabled [default off]]] Disabled] [comment if you notice the tight spacing in a lot of the lines, it's because the original parsers broken and leaks the space character when it shouldn't.] [div [id message] [class normal] [span [class label]Enter all of your e-mail addresses in this box, one address on a line] [div [class center] [textarea [reveal addresses] [class data] [name addresses] [rows 5] [columns 50] ]] [span [class label]I want the message to say:] [div [class center] [textarea [class data] [reveal_raw message] [name message] [rows 7] [columns 50] ]] [span[class label] once you've made changes to the above information, you must save it so it can take effect] ] [div [class center] [button [name commit] [class button] [value save] [type submit]] ] ]] ----------------sample code given Paul kindly gave me this example code but I'm having a hard time making heads or tails of it. For example, I can't figure out how to inject the text so can be parsed and how that information be presented so that the right bit such as the reveal where the arguments can be processed before the main command. One way to look at the markup language is that you walk the tree all the way to the bottom in that start filling in the blanks as you work your way up. It would be a depth first tree walk. One of the important features to maintain for the end user to create their own domain specific extensions. from pyparsing import * LBRACK,RBRACK = map(Suppress,'[]') escapedChar = Combine('\\' + oneOf(list(printables))) keyword = Word(alphas,alphanums).setName("keyword")#.setDebug() argword = Word(alphas,alphanums).setName("argword")#.setDebug() arg = Forward() dss = Forward() text = ZeroOrMore(escapedChar | originalTextFor(OneOrMore(Word(printables, excludeChars='[]"\'\\'))) | quotedString | dss) arg << Group(LBRACK + argword("arg") + Group(text)("text") + RBRACK) arg.setName("arg")#.setDebug() dss << Group(LBRACK + keyword("keyword") + Group(ZeroOrMore(arg))("args") + Group(text)("text") + RBRACK) parser = ZeroOrMore(dss) |