pyparsing-users Mailing List for Python parsing module (Page 9)
Brought to you by:
ptmcg
You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
(2) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(2) |
Feb
|
Mar
(2) |
Apr
(12) |
May
(2) |
Jun
|
Jul
|
Aug
(12) |
Sep
|
Oct
(1) |
Nov
|
Dec
|
2006 |
Jan
(5) |
Feb
(1) |
Mar
(10) |
Apr
(3) |
May
(7) |
Jun
(2) |
Jul
(2) |
Aug
(7) |
Sep
(8) |
Oct
(17) |
Nov
|
Dec
(3) |
2007 |
Jan
(4) |
Feb
|
Mar
(10) |
Apr
|
May
(6) |
Jun
(11) |
Jul
(1) |
Aug
|
Sep
(19) |
Oct
(8) |
Nov
(32) |
Dec
(8) |
2008 |
Jan
(12) |
Feb
(6) |
Mar
(42) |
Apr
(47) |
May
(17) |
Jun
(15) |
Jul
(7) |
Aug
(2) |
Sep
(13) |
Oct
(6) |
Nov
(11) |
Dec
(3) |
2009 |
Jan
(2) |
Feb
(3) |
Mar
|
Apr
|
May
(11) |
Jun
(13) |
Jul
(19) |
Aug
(17) |
Sep
(8) |
Oct
(3) |
Nov
(7) |
Dec
(1) |
2010 |
Jan
(2) |
Feb
|
Mar
(19) |
Apr
(6) |
May
|
Jun
(2) |
Jul
|
Aug
(1) |
Sep
|
Oct
(4) |
Nov
(3) |
Dec
(2) |
2011 |
Jan
(4) |
Feb
|
Mar
(5) |
Apr
(1) |
May
(3) |
Jun
(8) |
Jul
(6) |
Aug
(8) |
Sep
(35) |
Oct
(1) |
Nov
(1) |
Dec
(2) |
2012 |
Jan
(2) |
Feb
|
Mar
(3) |
Apr
(4) |
May
|
Jun
(1) |
Jul
|
Aug
(6) |
Sep
(18) |
Oct
|
Nov
(1) |
Dec
|
2013 |
Jan
(7) |
Feb
(7) |
Mar
(1) |
Apr
(4) |
May
|
Jun
|
Jul
(1) |
Aug
(5) |
Sep
(3) |
Oct
(11) |
Nov
(3) |
Dec
|
2014 |
Jan
(3) |
Feb
(1) |
Mar
|
Apr
(6) |
May
(10) |
Jun
(4) |
Jul
|
Aug
(5) |
Sep
(2) |
Oct
(4) |
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(13) |
May
(1) |
Jun
|
Jul
(2) |
Aug
|
Sep
(9) |
Oct
(2) |
Nov
(11) |
Dec
(2) |
2016 |
Jan
|
Feb
(3) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
(4) |
2017 |
Jan
(2) |
Feb
(2) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
(4) |
Nov
(3) |
Dec
|
2018 |
Jan
(10) |
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
|
2019 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2020 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2022 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2023 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2024 |
Jan
|
Feb
(1) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
(1) |
Aug
(3) |
Sep
(1) |
Oct
(1) |
Nov
|
Dec
|
From: John W. S. <jo...@nm...> - 2012-01-04 02:45:55
|
The countedText() pattern I posted on this thread did not work when the literal text extended over multiple lines. Below, an updated version that fixes that. Also expanded the comments and cleaned up some details. Best regards, John Shipman (jo...@nm...), Applications Specialist, NM Tech Computer Center, Speare 146, Socorro, NM 87801, (575) 835-5735, http://www.nmt.edu/~john ``Let's go outside and commiserate with nature.'' --Dave Farber ================================================================ #!/usr/bin/env python3 #================================================================ # countedtext: Using pyparsing for a string preceded by a count #---------------------------------------------------------------- # Author: John W. Shipman (jo...@nm...) # New Mexico Tech Computer Center # Socorro, NM 87801 # # Problem: Sanjay Ghemawat's venerable 'ical' calendar utility # (http://en.wikipedia.org/wiki/Ical_%28Unix%29) saves events # in a .calendar file, in which the description of an event # is saved in a line like this: # # Text [6 [Easter]] # # The problem is to write a pyparsing pattern that parses the # count and the bracketed string. The shortcut method is to # use QuotedString(quoteChar='[', endQuoteChar=']'), but this # fails if the literal string contains a ']' character. # # Paul McGuire responded immediately to my post on the pyparsing # mailing list, suggesting that I study the implementation of the # countedArray() helper. Based on this advice, I offer this # implementation of a countedText() pattern that matches an # integer followed by a literal string in brackets, complete # with a test driver. # 2012-01-03: Now allows newlines in the literal string. # Also expanded the comments and simplified some code. # To convert to Python 2.7: # - Removed '3' from the end of the first line. # - Uncommend the __future__ just below. # 2012-01-01: Initial version. #---------------------------------------------------------------- ####from __future__ import print_function import sys import re import pyparsing as pp def countedText(): '''Defines a pattern of the form: N "[" char* "]" where N is an integer that specifies the length of the following bracketed string literal. Example: "6 [Easter]" ''' #-- # The basic trick is to use Forward to create a dummy token # whose content can be filled in later. The time sequence: # A. When countedText() is called: # - Define a pattern 'intExpr' for N, and attach a parse # action to it that converts to type int. # - Use Forward() to create a dummy token 'stringExpr' # that will eventually match the (char*) of the pattern. # - Create a closure named 'countedParseAction' and attach it # as a parse action to intExpr. # - Return a pattern that matches the whole construct, with # the dummy token at the position of the (char*) part. # B. When intExpr is matched: # - Its first parse action converts the value to type int. # - Its second parse action is the countedParseAction() # closure, which extracts N from the token list t. # - It creates a pattern that matches exactly N characters, # including newlines. The '<<' operator for the Forward # class is overloaded to drop the real pattern in place # of the dummy pattern. #-- intExpr = pp.Word(pp.nums).setParseAction(lambda t: int(t[0])) stringExpr = pp.Forward() def countedParseAction(s, l, t): '''Parse action that sets up the count in stringExpr. To match the part between the brackets, we use a regex of the form ".{N}". This works even for N=0. The re.DOTALL flag makes "." match any character, even newline. ''' n = int(t[0]) stringExpr << pp.Combine( pp.Suppress("[") + pp.Regex(".{{{0:d}}}".format(n), re.DOTALL) + pp.Suppress("]")) return [] #-- # The second parse action uses the count to define the # stringExpr pattern using the actual value of the count. #-- intExpr.addParseAction(countedParseAction) return (intExpr + stringExpr) # - - - - - m a i n testLines = [ # Test output "0 []", # [''] "11 [abcdefghijk]", # ['abcdefghijk'] "6 [Easter]", # ['Easter'] "4 []]]]]", # [']]]]]]'] "6 [123\n56]", # ['123\n56'] "6 [ abcdef]" # Fails (leading whitespace not skipped) ] LINE_PAT = countedText() def main(): """Main """ for line in testLines: test(line) def test(line): '''Test one line ''' try: result = LINE_PAT.parseString(line, parseAll=True) print("/{0}/ -> {1}".format(line, result)) except pp.ParseException as x: print("{0}\n{1}^ Fail".format(line, " "*(x.column-1))) # - - - - - E p i l o g u e if __name__ == "__main__": main() |
From: John W. S. <jo...@nm...> - 2012-01-01 19:31:34
|
#!/usr/bin/env python3 #================================================================ # countedtext: Using pyparsing for a string preceded by a count #---------------------------------------------------------------- # Author: John W. Shipman (jo...@nm...) # New Mexico Tech Computer Center # Socorro, NM 87801 # # Problem: Sanjay Ghemawat's venerable 'ical' calendar utility # (http://en.wikipedia.org/wiki/Ical_%28Unix%29) saves events # in a .calendar file, in which the description of an event # is saved in a line like this: # # Text [6 [Easter]] # # The problem is to write a pyparsing pattern that parses the # count and the bracketed string. The shortcut method is to # use QuotedString(quoteChar='[', endQuoteChar=']'), but this # fails if the literal string contains a ']' character. # # Paul McGuire responded immediately to my post on the pyparsing # mailing list, suggesting that I study the implementation of the # countedArray() helper. Based on this advice, I offer this # implementation of a countedText() pattern that matches an # integer followed by a literal string in brackets, complete # with a test driver. #---------------------------------------------------------------- import sys import pyparsing as pp def countedText(): '''Defines a pattern of the form: int "[" char* "]" where int is an integer that specifies the length of the following bracketed string literal. Example: "6 [Easter]" ''' stringExpr = pp.Forward() def countedParseAction(s, l, t): '''Parse action that sets up the count in stringExpr. ''' n = int(t[0]) #-- # CharsNotIn does not like exact=0. We use Combine so that # whichever pattern represents the contents, the result is # a single string. #-- if n > 0: contents = pp.CharsNotIn('', exact=n) else: contents = pp.Empty() stringExpr << pp.Combine(pp.Literal("[").suppress() + contents + pp.Literal("]").suppress()) return [] #-- # The first parse action converts the count to an int. #-- intExpr = pp.Word(pp.nums).setParseAction(lambda t: int(t[0])) #-- # The second parse action uses the count to define the # stringExpr pattern using the actual value of the count. #-- intExpr.addParseAction(countedParseAction) return (intExpr + stringExpr) linePat = countedText() # - - - - - m a i n testLines = [ # Test output "0 []", # [''] "11 [abcdefghijk]", # ['abcdefghijk'] "6 [Easter]", # ['Easter'] "4 [[[]]]", # ['[[]]'] "6 []]]]]]]", # [']]]]]]'] "6 [ abcdef]" # Fails (leading whitespace not skipped) ] def main(): """Main """ for line in testLines: test(line) def test(line): '''Test one line ''' print("\n", line, sep='') try: result = linePat.parseString(line, parseAll=True) print(result) except pp.ParseException as x: print("{}^".format(" "*(x.column-1))) print("No") # - - - - - E p i l o g u e if __name__ == "__main__": main() |
From: Paul M. <pt...@au...> - 2011-12-31 23:01:03
|
John - Sorry you were disappointed in GSWP; I had proposed a longer outline to O'Reilly which included a reference section, but this would have inflated the book beyond the 60-70 page length which was their ebook target at the time. Please take a look at how countedArray is implemented in the pyparsing code. I think you could copy this method and write a countedLengthTextString method using the same principles. If you are still spinning your wheels, write back! -- Paul (There are docs, how-to's, UML diagrams, and many examples included in the source distribution, please see if that material helps flesh out what you didn't get from GSWP. Also, there is online htmldoc (generated by epydoc) at http://packages.python.org/pyparsing/, and a link to an HTML how-to at http://pyparsing.svn.sourceforge.net/viewvc/pyparsing/src/HowToUsePyparsing. html.) -----Original Message----- From: John W. Shipman [mailto:jo...@nm...] Sent: Saturday, December 31, 2011 2:40 PM To: Pyp...@li... Subject: [Pyparsing] fixed-length field preceded by length? I'm trying to parse the .calendar file used by the old Unix ical calendar program (the one written by Sanjay Ghemawat, not any of the modern iCal utilities). Here is a typical line from this file: Text [6 [Easter]] As you can see, the length is given explicitly, followed by whitespace, and the text string in brackets. How do I write the pyparsing syntax for lines of this form? The length may be any number, and I'd like to handle the case where '[' or ']' characters occur inside the text string. It's quite straightforward to write the patterns, but how do I write the pattern for the text string in such a way that it gets the length from a previous token in the same pattern? I just paid $10 for Paul McGuire's "Getting Started" eBook and was quite disappointed that there's no reference section, and no obvious solution to my problem. Any suggestions? Best regards (and happy new year!), John Shipman (jo...@nm...), Applications Specialist, NM Tech Computer Center, Speare 146, Socorro, NM 87801, (575) 835-5735, http://www.nmt.edu/~john ``Let's go outside and commiserate with nature.'' --Dave Farber ---------------------------------------------------------------------------- -- Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex infrastructure or vast IT resources to deliver seamless, secure access to virtual desktops. With this all-in-one solution, easily deploy virtual desktops for less than the cost of PCs and save 60% on VDI infrastructure costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox _______________________________________________ Pyparsing-users mailing list Pyp...@li... https://lists.sourceforge.net/lists/listinfo/pyparsing-users |
From: John W. S. <jo...@nm...> - 2011-12-31 20:40:00
|
I'm trying to parse the .calendar file used by the old Unix ical calendar program (the one written by Sanjay Ghemawat, not any of the modern iCal utilities). Here is a typical line from this file: Text [6 [Easter]] As you can see, the length is given explicitly, followed by whitespace, and the text string in brackets. How do I write the pyparsing syntax for lines of this form? The length may be any number, and I'd like to handle the case where '[' or ']' characters occur inside the text string. It's quite straightforward to write the patterns, but how do I write the pattern for the text string in such a way that it gets the length from a previous token in the same pattern? I just paid $10 for Paul McGuire's "Getting Started" eBook and was quite disappointed that there's no reference section, and no obvious solution to my problem. Any suggestions? Best regards (and happy new year!), John Shipman (jo...@nm...), Applications Specialist, NM Tech Computer Center, Speare 146, Socorro, NM 87801, (575) 835-5735, http://www.nmt.edu/~john ``Let's go outside and commiserate with nature.'' --Dave Farber |
From: mammar <ma...@gm...> - 2011-11-01 12:16:42
|
Hi All, I am a newbie to parsing and pyparsing. Here is my problem input string could be one of the following: - an integer number(could be negative) - an integer number(could be negative) and STR1 and STR2 whereas STR1 is a single word(alphas only) whereas STR2 is a string of alphas with spaces in between words i wrote the following pyparsing code but both print statements are printing -1 only, what is wrong? A general question related to parsing and pyparsing, what should be the output if 1. pattern matched 2. pattern not matched from pyparsing import * #exmple input strings str1 = "-1" str2 = "-1 ENOENT (No such file or directory)" neg = Word("-", exact=1) returnCodeNum = Combine(neg + Word(nums)) returnCodeSymbol = Word(alphas) returnInfo = OneOrMore(Word(alphas)) returnCodeInfo = Combine("(" + returnInfo + ")") rv2 = Combine( returnCodeNum + returnCodeSymbol + returnCodeInfo ) rv = returnCodeNum | rv2 print rv.parseString(str1) print rv.parseString(str2) |
From: Aubrey B. <ba...@cs...> - 2011-10-04 16:33:47
|
Paul, I want to thank you for providing such thorough help on this issue. It turns out I was 90% of the way there and just needed to connect a few more dots. What I Learned -------------- My main misunderstanding was related to how parse actions and ParseResults work together. I now understand that a parse action is passed a ParseResult that functions like a list of tokens. Actually, it is a list of whatever is returned from deeper calls of parsing, so it can be tokens or AST objects or whatever. This list of children is accessed via ParseResult.asList(). So all a parse action has to do to create an AST is package up its children appropriately into some AST object and return that object. If you take this approach groups are unnecessary. I only used a group once when I needed to handle multiplicity in one of the children of a pyparsing element and didn't want to create another pyparsing element specifically for that "sub-expression". (I effectively combined multiple levels/elements in my grammar into one pyparsing element and thus needed a bit of extra structure.) For example (sufficient excerpts to illustrate): def getAstFromParseResult(parseResult): return parseResult.asList()[0] # Packages a single token as an atomic AST object def astVariableParseAction(parseResult): return ('variable', getAstFromParseResult(parseResult)) # Packages named "sub-expressions" into an AST object # "head" is an AST object from a deeper call # "body" can have multiple children in the AST, so the whole ParseResult list is incorporated def astClauseParseAction(parseResult): return ('clause', ('head', parseResult.head), ('body', parseResult.body.asList())) clause.setParseAction(astClauseParseAction) Further response ---------------- In my case I really do need an AST and strings are my "object representation." My task is to parse the Prolog, gather some information about it, compile some related information from a different source, and spit out the original with annotations as comments. The annotations include both specific and aggregate information so I need to process the whole AST before starting output. In the process I do end up converting a few parts of the AST to objects (e.g. certain integers that are keys for other information), but the majority of the AST elements need no conversion and all have to be output as strings, so a "full" object representation would actually be more work. Prior to asking for help, I looked at some of the examples but most of them seemed to concentrate on implementing the grammar, not dealing with the results of parsing. No example description includes "ast" or "tree". Unfortunately, SimpleBool.py would not have helped clarify things for me as there is no mention of parse actions or parse results which were my main confusions. Feature Suggestion ------------------ Some form of incremental parsing would be a nice addition. I am thinking of situations (like Prolog) where you have many top-level elements to parse, but each is relatively simple. It would be nice to be able to parse them one-by-one in an iterative fashion: # lang :: ( comment | fact | clause )* for langElement in lang.parseIncremental(input): if langElement.name == 'fact': ... elif langElement.name == 'clause': ... ... This would allow parsing to scale well to large inputs as an entire AST would never have to be constructed. The only complication is handling when the repetition is a few levels down in the grammar (like class members in Java or body elements in HTML for example). (I could probably retrofit my task to the incremental model and see some fair efficiency gains.) Aubrey On 09/29/2011 01:10 AM, Paul McGuire wrote: > Aubrey - > > If all you want is an AST, then you should be able to construct this using > Group's and parseActions. For instance, let's say you want a parser for an > assignment statement, where the lvalue can be a variable and the rvalue can > be simple expression, with terms that can be integers, variables, or > function calls. > > """ > Simple BNF: > > assignment :: lvalue '=' rvalue > lvalue :: variableRef > rvalue :: term [ op term ] > term :: fnCall | variable | integer > fnCall :: fnName '(' [rvalue[,rvalue]*] ') > variable :: [a-zA-Z_][a-zA-Z0-9_]* > integer :: \d+ > op :: '+' | '-' > """ > > from pyparsing import * > > LPAR,RPAR,EQ = map(Suppress, "()=") > op = oneOf("+ -") > integer = Word(nums) > identifier = Word(alphas+'_', alphanums+'_') > variableRef = identifier.copy() > fnName = identifier.copy() > rvalue = Forward() > arglist = delimitedList(rvalue) > fnCall = fnName + Group(LPAR + Optional(arglist, default=[]) + RPAR) > rvalue<< (fnCall | variableRef | integer) > assignment = variableRef + EQ + Group(rvalue) > > print assignment.parseString("y = sin(60)-180").asList() > > Will print: > > ['y', ['sin', ['60']]] > > Knowing that this was an assignment statement, you could then use assignment > unpacking to pull out the left and right hand sides of the assignment: > > lhs, rhs = assignment.parseString("...").asList() > > > With some simple parse actions, you can decorate these structures similar to > what you show in your AST example: > > assignment.setParseAction(lambda t : ['assign'] + t.asList()) > fnCall.setParseAction(lambda t : ['function-call'] + t.asList()) > print assignment.parseString("y = sin(60)-180").asList() > > will print: > > ['assign', 'y', ['function-call', 'sin', ['60']]] > > > But now I have to ask, what do you plan to do with this AST? I suspect that > the next step is to walk the structure, and perform actions depending on the > decorating labels. Instead, I would suggest you use the parse actions to > construct representational objects. At parse time, you already know what > the substructures are going to be ("a function call will have a name and a > potentially empty argument list" for instance), why not use a parse action > to construct an object that gives a representation for this? > > class ASTNode(object): > def __init__(self, tokens): > self.tokens = tokens > self.assignFields() > def __str__(self): > return self.__class__.__name__ + ':' + str(self.__dict__) > __repr__ = __str__ > > class Assignment(ASTNode): > def assignFields(self): > self.lhs, self.rhs = self.tokens > del self.tokens > > class FunctionCall(ASTNode): > def assignFields(self): > self.fnName, self.args = self.tokens > del self.tokens > fnCall.setParseAction(FunctionCall) > assignment = (variableRef + EQ + rvalue).setParseAction(Assignment) > > print assignment.parseString("y = sin(60)-180")[0] > > Will print: > > Assignment:{'rhs': FunctionCall:{'fnName': 'sin', 'args': (['60'], {})}, > 'lhs': 'y'} > > > Now we have bypassed the intermediate AST step, and gone straight to an > object representation. These classes can be extended to include an eval or > exec method, which could be directly called, instead of retracing steps > already taken during parse time - why test args with isdigit, for instance? > At parse time, your grammar already defines when an integer is being > encountered - just add a parse action that does the string-to-integer > conversion. > > I think the SimpleBool.py example on the pyparsing wiki gives a more > complete treatment of this concept. In the article I wrote for Python > magazine, I showed how you could even pickle these representational objects, > and then unpickle and execute them in varying VM's (GUI, console, server) > without reparsing the original code. > > If you just want an AST, use Groups to add structure, and parse actions to > decorate the groups with your AST structure labels. I think though that the > representational objects are more powerful. > > -- Paul > > > > > -----Original Message----- > From: Aubrey Barnard [mailto:ba...@cs...] > Sent: Wednesday, September 28, 2011 7:35 PM > To: pyp...@li... > Subject: [Pyparsing] ParseResults as AST? > > Pyparsing users, > > I am having trouble figuring out how to make an abstract syntax tree > (AST) from a ParseResults object. I do not understand the data model > that is the ParseResults object as it relates to holding the information > of an AST. (I have spent a whole day on this so far, so it is time to > ask for help.) > > I am writing a Prolog parser, so I really do need an AST as opposed to > some flattened representation like ParseResults. Order matters. Type > matters. Depth matters. > > Sample Input > ------------ > > This is only Datalog with atoms, integers, and variables. > > ''' > % Facts > r1(a). r1(b). r1(c). > r2(a, 1). r2(a, 2). r2(d, 3). r2(e, 4). > % Clauses > r3(A, B) :- > r1(A), > r2(A, B). > ''' > > Desired Output > -------------- > > I would like to get something back from parsing like the following: > > ('datalog', > [ > ('comment', '% Facts'), > ('fact', [('name', 'r1'), ('body', [('atom', 'a')])]), > ('fact',<result>), > ... > ('clause', [('head',<result>), ('body', [<result>...])]), > ] > ) > > where<result> stands for the parse result from deeper recursion. The > structure is just lists of pairs. Each pair is the name (type) of the > parsed object and its content, the result. > > Parsing > ------- > > I believe I have my grammar implemented correctly in pyparsing as I get > the expected AST back as XML by calling ParseResults.asXML(). (Except > that I have an extra top-level element, > "<datalog><datalog>...</datalog></datalog>", but that is easy to > workaround.) > > Tried > ----- > > I have tried to understand the ParseResults object. Clearly the AST > information exists as ParseResults.asXML() gives me an AST in XML. > However, some of the information used in asXML() is not part of the > public API. > > I have tried to use parse actions to construct my own AST but I couldn't > figure this out either (in part because the product of parsing is still > a ParseResults object). > > Options > ------- > > * Use asXML() and reparse the XML. Not performant. Too much code. Misses > the point. > * Write asAST() into pyparsing.py as a near clone of asXML(). This is my > current favorite option. (I'm on a deadline.) > * Use parse actions effectively. > * Use a different parsing library (I have also tried pyPEG.) > * Other? > > Any suggestions and/or help would be very much appreciated. > > Sincerely, > > Aubrey > > ---------------------------------------------------------------------------- > -- > All the data continuously generated in your IT infrastructure contains a > definitive record of customers, application performance, security > threats, fraudulent activity and more. Splunk takes this data and makes > sense of it. Business sense. IT sense. Common sense. > http://p.sf.net/sfu/splunk-d2dcopy1 > _______________________________________________ > Pyparsing-users mailing list > Pyp...@li... > https://lists.sourceforge.net/lists/listinfo/pyparsing-users > |
From: Russell D. <Rus...@as...> - 2011-09-30 03:05:31
|
> No Group required, and the parsed results look okay. Group() actually breaks it, so the naming is required instead. As for the results, I was looking at the output without dump, my bad. >>> lang = Word("A") & ZeroOrMore(Word("B")("Bs")) >>> lang.parseString("B A B", parseAll=True) (['B', 'A', 'B'], {'Bs': [('B', 0), ('B', 2), ((['B', 'B'], {}), 0)]}) Its correct. |
From: Paul M. <pt...@au...> - 2011-09-30 02:44:35
|
Russell - Still not seeing the problem. from pyparsing import * """ language = expr1 & expr2 & Optional(expr3) & ZeroOrMore(expr4) & ZeroOrMore(expr5) """ A = oneOf("A a")("As") B = oneOf("B b")("Bs") C = oneOf("C c")("Cs") D = oneOf("D d")("Ds") E = oneOf("E e")("Es") lang = A & B & Optional(C) & ZeroOrMore(D) & ZeroOrMore(E) tests = """\ ABCDE ABDE AB BA EDCBA EaEB BeDCADEeDEDDeDD""".splitlines() for t in tests: print t.strip() print lang.parseString(t, parseAll=True).dump() print Prints: ABCDE ['A', 'B', 'C', 'D', 'E'] - As: A - Bs: B - Cs: C - Ds: D - Es: E ABDE ['A', 'B', 'D', 'E'] - As: A - Bs: B - Ds: D - Es: E AB ['A', 'B'] - As: A - Bs: B BA ['B', 'A'] - As: A - Bs: B EDCBA ['E', 'D', 'C', 'B', 'A'] - As: A - Bs: B - Cs: C - Ds: D - Es: E EaEB ['E', 'a', 'E', 'B'] - As: a - Bs: B - Es: ['E', 'E'] BeDCADEeDEDDeDD ['B', 'e', 'D', 'C', 'A', 'D', 'E', 'e', 'D', 'E', 'D', 'D', 'e', 'D', 'D'] - As: A - Bs: B - Cs: C - Ds: ['D', 'D', 'D', 'D', 'D', 'D', 'D'] - Es: ['e', 'E', 'e', 'E', 'e'] No Group required, and the parsed results look okay. -- Paul |
From: Russell D. <Rus...@as...> - 2011-09-29 23:43:58
|
On Thu, Sep 29, 2011 at 4:09 PM, Paul McGuire <pt...@au...> wrote: > Russell - > > I'm not seeing this behavior: > > EAEB > ['E', 'A', 'E', 'B'] > > You can have as many D's and E's as you like, anywhere, and at most 1 C > anywhere, but you must have 1 A and 1 B, somewhere. Odd, at some point I must have convinced myself something about Each that wasn't true. Ok, minor issue though, the Group keyword seems to cause this to stop working. Since the order doesn't matter, it'd be nice to Group them together. Naming them seems to be a workaround, but it produces strange parse output. ZeroOrMore(Literal("E")("Es"))) > > -----Original Message----- > From: Russell Dill [mailto:Rus...@as...] > Sent: Thursday, September 29, 2011 1:25 PM > To: pyp...@li... > Subject: [Pyparsing] Unordered set of expressions > > I have to parse something with an unordered set of expressions. In the > simplest case, some expressions are required, some are optional. For > this, parsing is easy: > > language = expr1 & expr2 & Optional(expr3) > > However, there are cases where an expression can occur zero or more > times, one or more times, or two or more times. But since they can > still occur in any order, I'm not sure how to handle it. If I try: > > language = expr1 & expr2 & Optional(expr3) & ZeroOrMore(expr4) & > ZeroOrMore(expr5) > > Then parsing fails if all expr4's are not adjacent. My current idea is > to do the following: > > multiples = ZeroOrMore(expr4 | expr5) > > language = (multiples + expr1) & (multiples + expr2) & > Optional(multiples + expr3) & multiples > > While its ugly, I can't think of any other way to do it. Additionally, > it doesn't get me any closer to implementing OneOrMore in an unsorted > set of expressions. > > ---------------------------------------------------------------------------- > -- > All the data continuously generated in your IT infrastructure contains a > definitive record of customers, application performance, security > threats, fraudulent activity and more. Splunk takes this data and makes > sense of it. Business sense. IT sense. Common sense. > http://p.sf.net/sfu/splunk-d2dcopy1 > _______________________________________________ > Pyparsing-users mailing list > Pyp...@li... > https://lists.sourceforge.net/lists/listinfo/pyparsing-users > > |
From: Paul M. <pt...@au...> - 2011-09-29 23:09:22
|
Russell - I'm not seeing this behavior: from pyparsing import * """ language = expr1 & expr2 & Optional(expr3) & ZeroOrMore(expr4) & ZeroOrMore(expr5) """ A = Literal("A") B = Literal("B") C = Literal("C") D = Literal("D") E = Literal("E") lang = A & B & Optional(C) & ZeroOrMore(D) & ZeroOrMore(E) tests = """\ ABCDE ABDE AB BA EDCBA EAEB BEDCADEEDEDDEDD""".splitlines() for t in tests: print t print lang.parseString(t, parseAll=True) print prints: ABCDE ['A', 'B', 'C', 'D', 'E'] ABDE ['A', 'B', 'D', 'E'] AB ['A', 'B'] BA ['B', 'A'] EDCBA ['E', 'D', 'C', 'B', 'A'] EAEB ['E', 'A', 'E', 'B'] BEDCADEEDEDDEDD ['B', 'E', 'D', 'C', 'A', 'D', 'E', 'E', 'D', 'E', 'D', 'D', 'E', 'D', 'D'] All of my test cases parse successfully. This is using the latest pyparsing. You can have as many D's and E's as you like, anywhere, and at most 1 C anywhere, but you must have 1 A and 1 B, somewhere. -- Paul -----Original Message----- From: Russell Dill [mailto:Rus...@as...] Sent: Thursday, September 29, 2011 1:25 PM To: pyp...@li... Subject: [Pyparsing] Unordered set of expressions I have to parse something with an unordered set of expressions. In the simplest case, some expressions are required, some are optional. For this, parsing is easy: language = expr1 & expr2 & Optional(expr3) However, there are cases where an expression can occur zero or more times, one or more times, or two or more times. But since they can still occur in any order, I'm not sure how to handle it. If I try: language = expr1 & expr2 & Optional(expr3) & ZeroOrMore(expr4) & ZeroOrMore(expr5) Then parsing fails if all expr4's are not adjacent. My current idea is to do the following: multiples = ZeroOrMore(expr4 | expr5) language = (multiples + expr1) & (multiples + expr2) & Optional(multiples + expr3) & multiples While its ugly, I can't think of any other way to do it. Additionally, it doesn't get me any closer to implementing OneOrMore in an unsorted set of expressions. ---------------------------------------------------------------------------- -- All the data continuously generated in your IT infrastructure contains a definitive record of customers, application performance, security threats, fraudulent activity and more. Splunk takes this data and makes sense of it. Business sense. IT sense. Common sense. http://p.sf.net/sfu/splunk-d2dcopy1 _______________________________________________ Pyparsing-users mailing list Pyp...@li... https://lists.sourceforge.net/lists/listinfo/pyparsing-users |
From: Russell D. <Rus...@as...> - 2011-09-29 18:25:23
|
I have to parse something with an unordered set of expressions. In the simplest case, some expressions are required, some are optional. For this, parsing is easy: language = expr1 & expr2 & Optional(expr3) However, there are cases where an expression can occur zero or more times, one or more times, or two or more times. But since they can still occur in any order, I'm not sure how to handle it. If I try: language = expr1 & expr2 & Optional(expr3) & ZeroOrMore(expr4) & ZeroOrMore(expr5) Then parsing fails if all expr4's are not adjacent. My current idea is to do the following: multiples = ZeroOrMore(expr4 | expr5) language = (multiples + expr1) & (multiples + expr2) & Optional(multiples + expr3) & multiples While its ugly, I can't think of any other way to do it. Additionally, it doesn't get me any closer to implementing OneOrMore in an unsorted set of expressions. |
From: Paul M. <pt...@au...> - 2011-09-29 06:10:59
|
Aubrey - If all you want is an AST, then you should be able to construct this using Group's and parseActions. For instance, let's say you want a parser for an assignment statement, where the lvalue can be a variable and the rvalue can be simple expression, with terms that can be integers, variables, or function calls. """ Simple BNF: assignment :: lvalue '=' rvalue lvalue :: variableRef rvalue :: term [ op term ] term :: fnCall | variable | integer fnCall :: fnName '(' [rvalue[,rvalue]*] ') variable :: [a-zA-Z_][a-zA-Z0-9_]* integer :: \d+ op :: '+' | '-' """ from pyparsing import * LPAR,RPAR,EQ = map(Suppress, "()=") op = oneOf("+ -") integer = Word(nums) identifier = Word(alphas+'_', alphanums+'_') variableRef = identifier.copy() fnName = identifier.copy() rvalue = Forward() arglist = delimitedList(rvalue) fnCall = fnName + Group(LPAR + Optional(arglist, default=[]) + RPAR) rvalue << (fnCall | variableRef | integer) assignment = variableRef + EQ + Group(rvalue) print assignment.parseString("y = sin(60)-180").asList() Will print: ['y', ['sin', ['60']]] Knowing that this was an assignment statement, you could then use assignment unpacking to pull out the left and right hand sides of the assignment: lhs, rhs = assignment.parseString("...").asList() With some simple parse actions, you can decorate these structures similar to what you show in your AST example: assignment.setParseAction(lambda t : ['assign'] + t.asList()) fnCall.setParseAction(lambda t : ['function-call'] + t.asList()) print assignment.parseString("y = sin(60)-180").asList() will print: ['assign', 'y', ['function-call', 'sin', ['60']]] But now I have to ask, what do you plan to do with this AST? I suspect that the next step is to walk the structure, and perform actions depending on the decorating labels. Instead, I would suggest you use the parse actions to construct representational objects. At parse time, you already know what the substructures are going to be ("a function call will have a name and a potentially empty argument list" for instance), why not use a parse action to construct an object that gives a representation for this? class ASTNode(object): def __init__(self, tokens): self.tokens = tokens self.assignFields() def __str__(self): return self.__class__.__name__ + ':' + str(self.__dict__) __repr__ = __str__ class Assignment(ASTNode): def assignFields(self): self.lhs, self.rhs = self.tokens del self.tokens class FunctionCall(ASTNode): def assignFields(self): self.fnName, self.args = self.tokens del self.tokens fnCall.setParseAction(FunctionCall) assignment = (variableRef + EQ + rvalue).setParseAction(Assignment) print assignment.parseString("y = sin(60)-180")[0] Will print: Assignment:{'rhs': FunctionCall:{'fnName': 'sin', 'args': (['60'], {})}, 'lhs': 'y'} Now we have bypassed the intermediate AST step, and gone straight to an object representation. These classes can be extended to include an eval or exec method, which could be directly called, instead of retracing steps already taken during parse time - why test args with isdigit, for instance? At parse time, your grammar already defines when an integer is being encountered - just add a parse action that does the string-to-integer conversion. I think the SimpleBool.py example on the pyparsing wiki gives a more complete treatment of this concept. In the article I wrote for Python magazine, I showed how you could even pickle these representational objects, and then unpickle and execute them in varying VM's (GUI, console, server) without reparsing the original code. If you just want an AST, use Groups to add structure, and parse actions to decorate the groups with your AST structure labels. I think though that the representational objects are more powerful. -- Paul -----Original Message----- From: Aubrey Barnard [mailto:ba...@cs...] Sent: Wednesday, September 28, 2011 7:35 PM To: pyp...@li... Subject: [Pyparsing] ParseResults as AST? Pyparsing users, I am having trouble figuring out how to make an abstract syntax tree (AST) from a ParseResults object. I do not understand the data model that is the ParseResults object as it relates to holding the information of an AST. (I have spent a whole day on this so far, so it is time to ask for help.) I am writing a Prolog parser, so I really do need an AST as opposed to some flattened representation like ParseResults. Order matters. Type matters. Depth matters. Sample Input ------------ This is only Datalog with atoms, integers, and variables. ''' % Facts r1(a). r1(b). r1(c). r2(a, 1). r2(a, 2). r2(d, 3). r2(e, 4). % Clauses r3(A, B) :- r1(A), r2(A, B). ''' Desired Output -------------- I would like to get something back from parsing like the following: ('datalog', [ ('comment', '% Facts'), ('fact', [('name', 'r1'), ('body', [('atom', 'a')])]), ('fact', <result>), ... ('clause', [('head', <result>), ('body', [<result>...])]), ] ) where <result> stands for the parse result from deeper recursion. The structure is just lists of pairs. Each pair is the name (type) of the parsed object and its content, the result. Parsing ------- I believe I have my grammar implemented correctly in pyparsing as I get the expected AST back as XML by calling ParseResults.asXML(). (Except that I have an extra top-level element, "<datalog><datalog>...</datalog></datalog>", but that is easy to workaround.) Tried ----- I have tried to understand the ParseResults object. Clearly the AST information exists as ParseResults.asXML() gives me an AST in XML. However, some of the information used in asXML() is not part of the public API. I have tried to use parse actions to construct my own AST but I couldn't figure this out either (in part because the product of parsing is still a ParseResults object). Options ------- * Use asXML() and reparse the XML. Not performant. Too much code. Misses the point. * Write asAST() into pyparsing.py as a near clone of asXML(). This is my current favorite option. (I'm on a deadline.) * Use parse actions effectively. * Use a different parsing library (I have also tried pyPEG.) * Other? Any suggestions and/or help would be very much appreciated. Sincerely, Aubrey ---------------------------------------------------------------------------- -- All the data continuously generated in your IT infrastructure contains a definitive record of customers, application performance, security threats, fraudulent activity and more. Splunk takes this data and makes sense of it. Business sense. IT sense. Common sense. http://p.sf.net/sfu/splunk-d2dcopy1 _______________________________________________ Pyparsing-users mailing list Pyp...@li... https://lists.sourceforge.net/lists/listinfo/pyparsing-users |
From: Aubrey B. <ba...@cs...> - 2011-09-29 01:35:10
|
Pyparsing users, I am having trouble figuring out how to make an abstract syntax tree (AST) from a ParseResults object. I do not understand the data model that is the ParseResults object as it relates to holding the information of an AST. (I have spent a whole day on this so far, so it is time to ask for help.) I am writing a Prolog parser, so I really do need an AST as opposed to some flattened representation like ParseResults. Order matters. Type matters. Depth matters. Sample Input ------------ This is only Datalog with atoms, integers, and variables. ''' % Facts r1(a). r1(b). r1(c). r2(a, 1). r2(a, 2). r2(d, 3). r2(e, 4). % Clauses r3(A, B) :- r1(A), r2(A, B). ''' Desired Output -------------- I would like to get something back from parsing like the following: ('datalog', [ ('comment', '% Facts'), ('fact', [('name', 'r1'), ('body', [('atom', 'a')])]), ('fact', <result>), ... ('clause', [('head', <result>), ('body', [<result>...])]), ] ) where <result> stands for the parse result from deeper recursion. The structure is just lists of pairs. Each pair is the name (type) of the parsed object and its content, the result. Parsing ------- I believe I have my grammar implemented correctly in pyparsing as I get the expected AST back as XML by calling ParseResults.asXML(). (Except that I have an extra top-level element, "<datalog><datalog>...</datalog></datalog>", but that is easy to workaround.) Tried ----- I have tried to understand the ParseResults object. Clearly the AST information exists as ParseResults.asXML() gives me an AST in XML. However, some of the information used in asXML() is not part of the public API. I have tried to use parse actions to construct my own AST but I couldn't figure this out either (in part because the product of parsing is still a ParseResults object). Options ------- * Use asXML() and reparse the XML. Not performant. Too much code. Misses the point. * Write asAST() into pyparsing.py as a near clone of asXML(). This is my current favorite option. (I'm on a deadline.) * Use parse actions effectively. * Use a different parsing library (I have also tried pyPEG.) * Other? Any suggestions and/or help would be very much appreciated. Sincerely, Aubrey |
From: thomas_h <th...@gm...> - 2011-09-28 19:56:55
|
Any update on this? To summarize, I wonder why this (character after start-of-line, with optional intervening whitespace, in a multi-line match) py.Regex(r'^\s*B', re.M).searchString('foo\nB') matches, while this py.Regex(r'^\s*B', re.M).searchString('foo\n B') doesn't (mind the space between '\n' and 'B' in the search string), while these two ('o' before end-of-line, with optional intervening whitespace, in a multi-line match) py.Regex(r'o\s*$', re.M).searchString('foo\nB') py.Regex(r'o\s*$', re.M).searchString('foo \nB') both match (capturing the whitespace in the second case). Why do the ^ and $ anchors behave differently? Thanks, Thomas |
From: Russell D. <Rus...@as...> - 2011-09-28 07:20:53
|
On Tue, Sep 27, 2011 at 10:58 PM, Paul McGuire <pt...@au...> wrote: > You can disable the backtracking within an a, b, c, or d by using the '-' > operator instead of '+': > > a = a_header - a_data > b = b_header - b_data > c = c_header - c_data > d = d_header - d_data > > I think this will accomplish what you wanted with Required. awesome, thanks, that's exactly what I was looking for. |
From: Paul M. <pt...@au...> - 2011-09-28 05:59:08
|
You can disable the backtracking within an a, b, c, or d by using the '-' operator instead of '+': a = a_header - a_data b = b_header - b_data c = c_header - c_data d = d_header - d_data I think this will accomplish what you wanted with Required. -- Paul -----Original Message----- From: Russell Dill [mailto:Rus...@as...] Sent: Wednesday, September 28, 2011 12:32 AM To: pyp...@li... Subject: [Pyparsing] Required Class? I have some text I'm parsing with headers and then data. The header/data groups can be in any order, aba, aabbba, acbd, bdacaa, etc (Where the letter represents a header type followed by its data). So overall, I have something like: a = a_header + a_data b = b_header + b_data c = c_header + c_data d = d_header + d_data ZeroOrMore(a | b | c | d) + EndTag Now, if a_header exists, but a_data is malformed, I get an error that it expected EndTag. For easier debugging, I'd like the error to make more sense, so: a = a_header + Required(a_data) where: class Required(ParseElementEnhance): def __init__(self, exprs): super(Required, self).__init__(exprs) def parseImpl(self, instring, loc, doActions=True): try: loc, tokens = self.expr._parse(instring, loc, doActions, callPreParse=False) except ParseException as e: raise ParseFatalException(e) return loc, tokens Is this the best way to go about this goal? Is there instead a better way of saying any number of any of these expressions in any order? If at least one (or exactly one) 'c' expression is required, is there a way of denoting that? ---------------------------------------------------------------------------- -- All the data continuously generated in your IT infrastructure contains a definitive record of customers, application performance, security threats, fraudulent activity and more. Splunk takes this data and makes sense of it. Business sense. IT sense. Common sense. http://p.sf.net/sfu/splunk-d2dcopy1 _______________________________________________ Pyparsing-users mailing list Pyp...@li... https://lists.sourceforge.net/lists/listinfo/pyparsing-users |
From: Russell D. <Rus...@as...> - 2011-09-28 05:31:41
|
I have some text I'm parsing with headers and then data. The header/data groups can be in any order, aba, aabbba, acbd, bdacaa, etc (Where the letter represents a header type followed by its data). So overall, I have something like: a = a_header + a_data b = b_header + b_data c = c_header + c_data d = d_header + d_data ZeroOrMore(a | b | c | d) + EndTag Now, if a_header exists, but a_data is malformed, I get an error that it expected EndTag. For easier debugging, I'd like the error to make more sense, so: a = a_header + Required(a_data) where: class Required(ParseElementEnhance): def __init__(self, exprs): super(Required, self).__init__(exprs) def parseImpl(self, instring, loc, doActions=True): try: loc, tokens = self.expr._parse(instring, loc, doActions, callPreParse=False) except ParseException as e: raise ParseFatalException(e) return loc, tokens Is this the best way to go about this goal? Is there instead a better way of saying any number of any of these expressions in any order? If at least one (or exactly one) 'c' expression is required, is there a way of denoting that? |
From: Russell D. <Rus...@as...> - 2011-09-27 01:27:33
|
I have a file format like this: [Component] foo data_foo [Model] red data_red [Component] bar data_bar [Model] blue data_blue [Model] green data_green I'd like to get something out with: results.Component { foo : data_foo, bar : data_bar } results.Model { red : data_red, blue : data_blue, green : data_green } So I have something like: class FileKeyword(ParserElement): def __new__(cls, name): cls = LineStart() + Literal('[') + Literal(name) + Literal(']') return cls parser = ZeroOrMore( \ Dict(Group( \ FileKeyword("Component").suppress() + Keyword(printables) + ZeroOrMore(Keyword(printables)) )).setResultsName("Component", True) | \ Dict(Group( FileKeyword("Model").suppress() + Keyword(printables) + ZeroOrMore(Keyword(printables)) )).setResultsName("Model", True) \ ) parser.parseString(<above>).dump() Which gives me a: - Component [[[ "foo", "data_foo" ]], [["bar", "data_bar"]]], but no Dict. |
From: Paul M. <pt...@au...> - 2011-09-26 13:05:05
|
Oops, left out this line: redefine_comment.setParseAction(redefine_current_comment_char) -- Paul |
From: Paul M. <pt...@au...> - 2011-09-26 12:58:44
|
That *does* seem weird, that the comment character can be changed on the fly like that. I would use a self-modifying expression, similar to what you see in the pyparsing code for matchPreviousLiteral or countedArray. In this case, you would define the comment expression as a Forward() and initialize it to the default comment character (let's say it's '#'). comment = Forward() comment << '#' + restOfLine Use expr.ignore(comment) just as you normally would. Then define your comment redefinition expression as: redefine_comment = "[Comment char]" + oneOf(list(printables))("newchar") + "_char" And attach a parse action to redefine_comment like this: def redefine_current_comment_char(tokens): comment << tokens.newchar + restOfLine I've never tried dynamically modifying an expression that gets ignored, you might have to do something else like Ralph Corderoy suggested, breaking up the input text into multiple "[Comment char]"-controlled blocks, parse each one separately, and then merge the results back together. Fortunately, the merging of results is very easy now, you can just put them into a list and combine them using: all_results = sum(list_of_results) Good luck! -- Paul -----Original Message----- From: Russell Dill [mailto:Rus...@as...] Sent: Sunday, September 25, 2011 9:29 PM To: pyp...@li... Subject: [Pyparsing] Variable comment char I need to parse a rather evil format that has the following line: [Comment Char] |_char Which would change the comment char to '|'. The comment char can be any non-alphanumeric printable other than [ or ] and the comment char ... |
From: Ralph C. <ra...@in...> - 2011-09-26 12:17:52
|
Hi Russell, > I need to parse a rather evil format that has the following line: > > [Comment Char] |_char > > Which would change the comment char to '|'. How about a two-pass approach? Have pyparsing handle just these `change comment char' commands with all the other text being stripped of comments, denoted by the current char, by Python code, then pyparse again with your full grammar knowing all comments have gone. Cheers, Ralph. |
From: Russell D. <Rus...@as...> - 2011-09-26 02:28:38
|
I need to parse a rather evil format that has the following line: [Comment Char] |_char Which would change the comment char to '|'. The comment char can be any non-alphanumeric printable other than [ or ] and the comment char can be changed at any time and as many times as desired. The non comment, non bracket characters are legal characters. Initially, I figured I'd hold onto the ParserElement objects in self and modify them in callbacks. However, it appears they get copied and thus modifying them does nothing. So I made a Token class that has an internal reference to something I can modify. This works for the comment char, but then I have the issue of parsing tokens that contains characters that could be comment characters. If I include all non printables in that word, then comments don't get ignored. What's the best way to do this? class DynamicCharHolder(): def __init__(self, char): self.match = char def getMatch(self): return self.match def setMatch(self, char): self.match = char class DynamicChar(Token): def __init__(self, holder): super(DynamicChar, self).__init__() self.holder = holder self.name = "DynamicChar" self.mayReturnEmpty = False self.mayIndexError = False def parseImpl(self, instring, loc, doActions=True ): if (instring[loc] == self.holder.getMatch()): print "match '" + instring[loc] + "' at " + str(loc) return loc + 1, instring[loc] exc = self.myException exc.loc = loc exc.pstr = instring raise exc class IBISParser: def setCommentDelim(self, tokens): self.holder.setMatch(tokens[0]) print "New comment delim " + tokens[0] def __init__(self, text): self.holder = DynamicCharHolder("|") comment_delim = DynamicChar(self.holder) comment = comment_delim + restOfLine [...] ibis_file.ignore(comment) |
From: Paul M. <pt...@au...> - 2011-09-25 14:25:23
|
Are you using operatorPrecedence? If so, then expand the definition of the operand expression that you are passing in to handle the optional indexing. As Ralph Corderoy already pointed out, your index is probably going to be another arithmetic expression, so you will need to define operand in terms of the expression that will be defined using operand -> the arithmetic expression will have to be defined as a Forward. Something like this: arith_expr = Forward() operand = number | variable+Optional('[' + arith_expr + ']') arith_expr << operatorPrecedence(operand, [ ... operator definitions go here ... ]) If your evaluator does not use operatorPrecedence, but you have done your own grammar expansion, you'll have to reinterpret this suggestion in the context of your own grammar structure. -- Paul -----Original Message----- From: Will McGugan [mailto:wil...@gm...] Sent: Sunday, September 25, 2011 7:30 AM To: Pyp...@li... Subject: [Pyparsing] Index operator Hi, I have a custom expression evaluator that is working quite well, bit I'd like to implement an operator that works just like indexing a string or sequence in python. i.e. something[<expression>] I can't quite figure out how to do this. Can anyone give me any pointers? Thanks, Will McGugan -- Will McGugan http://www.willmcgugan.com ---------------------------------------------------------------------------- -- All of the data generated in your IT infrastructure is seriously valuable. Why? It contains a definitive record of application performance, security threats, fraudulent activity, and more. Splunk takes this data and makes sense of it. IT sense. And common sense. http://p.sf.net/sfu/splunk-d2dcopy2 _______________________________________________ Pyparsing-users mailing list Pyp...@li... https://lists.sourceforge.net/lists/listinfo/pyparsing-users |
From: Ralph C. <ra...@in...> - 2011-09-25 13:11:54
|
Hi Will, > i.e. something[<expression>] > > I can't quite figure out how to do this. Can anyone give me any > pointers? Do you know of Forward()? http://pyparsing.wikispaces.com/file/view/SimpleCalc.py may help. What you want to do is similar to allowing parenthesis in an expression? Cheers, Ralph. |
From: Will M. <wil...@gm...> - 2011-09-25 12:29:52
|
Hi, I have a custom expression evaluator that is working quite well, bit I'd like to implement an operator that works just like indexing a string or sequence in python. i.e. something[<expression>] I can't quite figure out how to do this. Can anyone give me any pointers? Thanks, Will McGugan -- Will McGugan http://www.willmcgugan.com |