Re: [Pyparsing] How can I determine if a fragment is valid?
Brought to you by:
ptmcg
From: Paul M. <pt...@au...> - 2008-01-15 14:55:33
|
Thanks for the quick reply. So far using pe.loc < len(input) works for me. I'll reply to the list if I can find a counter example. Can I count on loc sticking around in the ParseException class? <PM> Great! Yes, loc is an important part of ParseException, and has been in pyparsing since version 0.5. What would give you the idea that it might not stick around? Not to push my luck, but I've got a grammar question too. I'm trying to define a grammar that uses a skipTo(Optional(xxx)) and not having much success. Is there a better way to go about this? select where foo = 1 and bar = 2 into result I was hoping to end up with something like the following: into_clause = Keyword('into') + restOfLine Keyword('select') + skipTo(Optional(into_clause)).setResultsName('where_condition') <PM> Hmm, SkipTo (leading "S" is capitalized) really wants to have a predictable target expression. SkipTo can be embedded inside an Optional, but you can't skip to an optional thing. You *can* skip to one thing or another, as in SkipTo(A | B), and the SkipTo will stop at whichever comes first. If A may or may not be present, then make B a StringEnd(). where_clause = SkipTo(into_clause | StringEnd()) This is actually almost readable English - "skip to either the into_clause or the end of the input string". But if all of your where clauses are this simple, you might take the time to define a where_clause expression, probably using operatorPrecedence to take care of things like nested parentheses. Here is how to use operatorPrecedence: 1. Identify the basic operand of your expression. In this case, each where clause is a boolean expression of logical comparisons. A logical comparison is of the form: identifer = Word(alphas) relationalOperator = oneOf("< = > >= <= != <>") integer = Word(nums) value = integer | sglQuotedString logicalComparison = identifier + relationalOperator + value 2. Identify the operators. Logical expressions usually allow AND, OR, and NOT. We'll define caseless versions of each: AND_cl = CaselessLiteral("AND") OR_cl = CaselessLiteral("OR") NOT_cl = CaselessLiteral("NOT") 3. Call operatorPrecedence with these operators, to compose a grammar. complexComparison = operatorPrecedence( logicalComparison, [ (NOT_cl, 1, opAssoc.RIGHT), (OR_cl, 2, opAssoc.LEFT), (AND_cl, 2, opAssoc.LEFT), ]) operatorPrecedence is called using the base operand, followed by a list of tuples describing each operator or group of operators. Each tuple contains the operator, the value 1 or 2 indicating whether it is a unary or binary operator, and the opAssoc.LEFT or opAssoc.RIGHT value indicating whether the operator is right or left associative. With the example you provided, this should be enough to define a where_clause expression: where_clause = CaselessLiteral("where") + complexComparison You may have to expand the value expression to support real numbers or identifiers, I hope this is clear how you would do so - what I've provided will match integers or single-quoted strings. Probably more than you asked for, if it is too much to deal with now, just go with the SkipTo alternative, and come back to the rest of this later. -- Paul |