pyparsing ParseException: Expected end of line -- general questions - python

I am a newbie to pyparsing and have been reading the examples, looking here and trying some things out.
I created a grammar and provided a buffer. I do however have a heavy background in lex/yacc from the old days.
I have a general question or two.
I'm currently seeing
ParseException: Expected end of line (at char 7024), (line 213, col:2)
and then it terminates
Because of the nature of my buffer, newlines have meaning, I did:
ParserElement.setDefaultWhitespaceChars('') # <-- zero len string
Does this error mean that somewhere in my productions, I have a rule that is looking for an LineEnd() and that rule happens to somehow be 'last'?
The location it is dying is the 'end of file'. I tried using parseFile but my file contains chars > ord(127) so instead I am loading it to memory, filtering all > ord(127) chars, then calling parseString.
I tried turning on verbose_stacktrace=True for some of the elements of my grammar where I thought the problem originated.
Is there a better way to track down the exact ParserElement it is trying to recognize when an error such as this occurs? Or can I get a 'stack or most recently recognized production trace?
I didn't realize I could edit up here...
My crash is this:
[centos#new-host /tmp/sample]$ ./zooparser.py
!(zooparser.py) TEST test1: valid message type START
Ready to roll
Parsing This message: ( ignore leading>>> and trailing <<< ) >>>
ZOO/STATUS/FOOD ALLOCATION//
TOPIC/BIRD FEED IS RUNNING LOW//
FREE/WE HAVE DISCOVERED MOTHS INFESTED THE BIRDSEED AND IT IS NO
LONGER USABLE.//
<<<
Match {Group:({Group:({Group:({[LineEnd]... "ZOO" Group:({[LineEnd]... "/" [Group:({{{W:(abcd...) | LineEnd | "://" | " " | W:(!##$...) | ":"}}... ["/"]...})]... {W:(abcd...) | LineEnd | "://" | " " | W:(!##$...)}}) "//"}) Group:({LineEnd "TOPIC" {Group:({[LineEnd]... Group:({"/" {W:(abcd...) | Group:({W:(abcd...) [{W:(abcd...)}...]... W:(abcd...)}) | Group:({{{"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'"}... | Group:({{"0123456789"}... ":"})} {W:(abcd...) | Group:({W:(abcd...) [{W:(abcd...)}...]... W:(abcd...)})}}) | "-"}})})}... [LineEnd]... "//"})}) [Group:({LineEnd "FREE" Group:({[LineEnd]... "/" [Group:({{{W:(abcd...) | LineEnd | "://" | " " | W:(!##$...) | ":"}}... ["/"]...})]... {W:(abcd...) | LineEnd | "://" | " " | W:(!##$...)}}) "//"})]...}) [LineEnd]... StringEnd} at loc 0(1,1)
Match Group:({Group:({[LineEnd]... "ZOO" Group:({[LineEnd]... "/" [Group:({{{W:(abcd...) | LineEnd | "://" | " " | W:(!##$...) | ":"}}... ["/"]...})]... {W:(abcd...) | LineEnd | "://" | " " | W:(!##$...)}}) "//"}) Group:({LineEnd "TOPIC" {Group:({[LineEnd]... Group:({"/" {W:(abcd...) | Group:({W:(abcd...) [{W:(abcd...)}...]... W:(abcd...)}) | Group:({{{"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'"}... | Group:({{"0123456789"}... ":"})} {W:(abcd...) | Group:({W:(abcd...) [{W:(abcd...)}...]... W:(abcd...)})}}) | "-"}})})}... [LineEnd]... "//"})}) at loc 0(1,1)
Match Group:({[LineEnd]... "ZOO" Group:({[LineEnd]... "/" [Group:({{{W:(abcd...) | LineEnd | "://" | " " | W:(!##$...) | ":"}}... ["/"]...})]... {W:(abcd...) | LineEnd | "://" | " " | W:(!##$...)}}) "//"}) at loc 0(1,1)
Exception raised:None
Exception raised:None
Exception raised:None
Traceback (most recent call last):
File "./zooparser.py", line 319, in <module>
test1(pgm)
File "./zooparser.py", line 309, in test1
test(pgm, zooMsg, 'test1: valid message type' )
File "./zooparser.py", line 274, in test
tokens = zg.getTokensFromBuffer(fileName)
File "./zooparser.py", line 219, in getTokensFromBuffer
tokens = self.text.parseString(filteredBuffer,parseAll=True)
File "/usr/local/lib/python2.7/site-packages/pyparsing-1.5.7-py2.7.egg/pyparsing.py", line 1006, in parseString
raise exc
pyparsing.ParseException: Expected end of line (at char 148), (line:8, col:2)
[centos#new-host /tmp/sample]$
source: see http://prj1.y23.org/zoo.zip

pyparsing takes a different view toward parsing than lex/yacc does. You have to let the classes do some of the work. Here's an example in your code:
self.columnHeader = OneOrMore(self.aucc) \
| OneOrMore(nums) \
| OneOrMore(self.blankCharacter) \
| OneOrMore(self.specialCharacter)
You are equating OneOrMore with the '+' character of a regex. In pyparsing, this is true for ParseElements, but at the character level, pyparsing uses the Word class:
self.columnHeader = Word(self.aucc + nums + self.blankCharacter + self.specialCharacter)
OneOrMore works with ParseElements, not characters. Look at:
OneOrMore(nums)
nums is the string "0123456789", so OneOrMore(nums) will match "0123456789", "01234567890123456789", etc., but not "123". That is what Word is for. OneOrMore will accept a string argument, but will implicitly convert it to a Literal.
This is a fundamental difference between using pyparsing and lex/yacc, and I think is the source of much of the complexity in your code.
Some other suggestions:
Your code has some premature optimizations in it - you write:
aucc = ''.join(set([alphas.upper(),"'"]))
Assuming that this will be used for defining Words, just do:
aucc = alphas.upper() + "'"
There is no harm in having duplicate characters in aucc, Word will convert this to a set internally.
Write a BNF for what you want to parse. It does not have to be overly rigorous as you would with lex/yacc. From your samples, it looks something like:
# sample
ZOO/STATUS/FOOD ALLOCATION//
TOPIC/BIRD FEED IS RUNNING LOW//
FREE/WE HAVE DISCOVERED MOTHS INFESTED THE BIRDSEED AND IT IS NO
LONGER USABLE.//
parser :: header topicEntry+
header :: "ZOO" sep namedValue
namedValue :: uppercaseWord sep valueBody
valueBody :: (everything up to //)
topicEntry :: topicHeader topicBody
topicHeader :: "TOPIC" sep valuebody
topicBody :: freeText
freeText :: "FREE" sep valuebody
sep :: "/"
Converting to pyparsing, this looks something like:
SEP = Literal("/")
BODY_TERMINATOR = Literal("//")
FREE_,TOPIC_,ZOO_ = map(Keyword,"FREE TOPIC ZOO".split())
uppercaseWord = Word(alphas.upper())
valueBody = SkipTo(BODY_TERMINATOR) # adjust later, but okay for now...
freeText = FREE_ + SEP + valueBody
topicBody = freeText
topicHeader = TOPIC_ + SEP + valueBody
topicEntry = topicHeader + topicBody
namedValue = uppercaseWord + SEP + valueBody
zooHeader = ZOO_ + SEP + namedValue
parser = zooHeader + OneOrMore(topicEntry)
(valueBody will have to get more elaborate when you add support for '://' embedded within a value, but save that for Round 2.)
Don't make things super complicated until you get at least some simple stuff working.

Related

Error when trying to print string with multiple lines

I'm trying to make a tic tac toe game in Python but whenever I try to print the board, I get a weird error. Here is my code:
import os
from colorama import Fore
board = " a b c\n | | \n1 - | - | - \n _____|_____|_____\n | | \n2 - | - | - \n _____|_____|_____\n | | \n3 - | - | - \n | | "
def board():
print(board)
board()
And this is the error:
 SIGQUIT: quit
PC=0x7f1a62b22792 m=0 sigcode=128
signal arrived during cgo execution
goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x4bb660, 0xc000066d90)
runtime/cgocall.go:156 +0x5c fp=0xc000066d68 sp=0xc000066d30 pc=0x40651c
main._Cfunc_PyRun_InteractiveLoopFlags(0x7f1a62be9800, 0x55555691b800, 0x0)
_cgo_gotypes.go:418 +0x4c fp=0xc000066d90 sp=0xc000066d68 pc=0x4b8e4c
main.Python.REPL.func2(0x55555691b800)
github.com/replit/prybar/languages/python3/main.go:122 +0x66 fp=0xc000066dd0 sp=0xc000066d90 pc=0x4bacc6
main.Python.REPL({})
github.com/replit/prybar/languages/python3/main.go:122 +0x99 fp=0xc000066e10 sp=0xc000066dd0 pc=0x4bac19
main.(*Python).REPL(0x5d56d0)
<autogenerated>:1 +0x2a fp=0xc000066e20 sp=0xc000066e10 pc=0x4bb36a
github.com/replit/prybar/utils.Language.REPL({{0x5075d0, 0x5d56d0}, {0x7ffd00c3ac79, 0x4e1680}})
github.com/replit/prybar/utils/language.go:100 +0x5d fp=0xc000066e78 sp=0xc000066e20 pc=0x4b825d
github.com/replit/prybar/utils.DoCli({0x5075d0, 0x5d56d0})
github.com/replit/prybar/utils/utils.go:77 +0x3d7 fp=0xc000066f60 sp=0xc000066e78 pc=0x4b8a97
main.main()
github.com/replit/prybar/languages/python3/generated_launch.go:7 +0x27 fp=0xc000066f80 sp=0xc000066f60 pc=0x4b8bc7
<function board at 0x7f5f840e2280>
I haven't seen a error like this before and am wondering what it means and how to fix it? Thanks for help!
The problem is that you are naming everything "board"
When you do "def board()" after "board = ..." you are redefining board to be a function and no longer a string.
The error you are getting is due to your editor somehow not supporting printing functions

Dealing with ZeroOrMore in pyparsing

I'm trying to parse pactl list with pyparsing: So far all parse is working correctly but I cannot make ZeroOrMore to work correctly.
I can find foo: or foo: bar and try to deal with that with ZeroOrMore but it doesn't work, I have to add special case "Argument:" to find results without value, but there're Argument: foo results (with value) so it will not work, and I expect any other property to exist without value.
With this definition, and a fixed pactl list output:
#!/usr/bin/env python
#
# parsing pactl list
#
from pyparsing import *
import os
from subprocess import check_output
import sys
data = '''
Module #6
Argument:
Name: module-alsa-card
Usage counter: 0
Properties:
module.author = "Lennart Poettering"
module.description = "ALSA Card"
module.version = "14.0-rebootstrapped"
'''
indentStack = [1]
stmt = Forward()
identifier = Word(alphanums+"-_.")
sect_def = Group(Group(identifier) + Suppress("#") + Group(Word(nums)))
inner_section = indentedBlock(stmt, indentStack)
section = (sect_def + inner_section)
value = Group(Group(Combine(OneOrMore(identifier|White(' ')))) + Suppress(":") + Group(Combine(ZeroOrMore(Word(alphanums+'-/=_".')|White(' ', max=1)))))
prop_name = Literal("Properties:")
prop_section = indentedBlock(stmt, indentStack)
prop_val = Group(Group(identifier) + Suppress("=") + Group(Combine(OneOrMore(Word(alphanums+'-"/.')|White(' \t')))))
prop = (prop_name + prop_section)
stmt << ( section | prop | ("Argument:") | value | prop_val )
syntax = OneOrMore(stmt)
parseTree = syntax.parseString(data)
parseTree.pprint()
This gets:
$ ./pactl.py
Module #6
Argument:
Name: module-alsa-card
Usage counter: 0
Properties:
module.author = "Lennart Poettering"
module.description = "ALSA Card"
module.version = "14.0-rebootstrapped"
[[['Module'], ['6']],
[['Argument:'],
[[['Name'], ['module-alsa-card']]],
[[['Usage counter'], ['0']]],
['Properties:',
[[[['module.author'], ['"Lennart Poettering"']]],
[[['module.description'], ['"ALSA Card"']]],
[[['module.version'], ['"14.0-rebootstrapped"']]]]]]]
So far so good, but removing special case for Argument: it gets into error, as ZeroOrMore doesn't behave as expected:
#!/usr/bin/env python
#
# parsing pactl list
#
from pyparsing import *
import os
from subprocess import check_output
import sys
data = '''
Module #6
Argument:
Name: module-alsa-card
Usage counter: 0
Properties:
module.author = "Lennart Poettering"
module.description = "ALSA Card"
module.version = "14.0-rebootstrapped"
'''
indentStack = [1]
stmt = Forward()
identifier = Word(alphanums+"-_.")
sect_def = Group(Group(identifier) + Suppress("#") + Group(Word(nums)))
inner_section = indentedBlock(stmt, indentStack)
section = (sect_def + inner_section)
value = Group(Group(Combine(OneOrMore(identifier|White(' ')))) + Suppress(":") + Group(Combine(ZeroOrMore(Word(alphanums+'-/=_".')|White(' ', max=1))))).setDebug()
prop_name = Literal("Properties:")
prop_section = indentedBlock(stmt, indentStack)
prop_val = Group(Group(identifier) + Suppress("=") + Group(Combine(OneOrMore(Word(alphanums+'-"/.')|White(' \t')))))
prop = (prop_name + prop_section)
stmt << ( section | prop | value | prop_val )
syntax = OneOrMore(stmt)
parseTree = syntax.parseString(data)
parseTree.pprint()
This results in:
$ ./pactl.py
Module #6
Argument:
Name: module-alsa-card
Usage counter: 0
Properties:
module.author = "Lennart Poettering"
module.description = "ALSA Card"
module.version = "14.0-rebootstrapped"
Match Group:({Group:(Combine:({{W:(ABCD...) | <SP>}}...)) Suppress:(":") Group:(Combine:([{W:(ABCD...) | <SP>}]...))}) at loc 19(3,9)
Matched Group:({Group:(Combine:({{W:(ABCD...) | <SP>}}...)) Suppress:(":") Group:(Combine:([{W:(ABCD...) | <SP>}]...))}) -> [[['Argument'], ['Name']]]
Match Group:({Group:(Combine:({{W:(ABCD...) | <SP>}}...)) Suppress:(":") Group:(Combine:([{W:(ABCD...) | <SP>}]...))}) at loc 1(2,1)
Exception raised:Expected ":", found '#' (at char 8), (line:2, col:8)
Traceback (most recent call last):
File "/home/alberto/projects/node/pacmd_list_json/./pactl.py", line 55, in <module>
parseTree = syntax.parseString(partial)
File "/usr/local/lib/python3.9/site-packages/pyparsing.py", line 1955, in parseString
raise exc
File "/usr/local/lib/python3.9/site-packages/pyparsing.py", line 6336, in checkUnindent
raise ParseException(s, l, "not an unindent")
pyparsing.ParseException: Expected {{Group:({Group:(W:(ABCD...)) Suppress:("#") Group:(W:(0123...))}) indented block} | {"Properties:" indented block} | Group:({Group:(Combine:({{W:(ABCD...) | <SP>}}...)) Suppress:(":") Group:(Combine:([{W:(ABCD...) | <SP>}]...))}) | Group:({Group:(W:(ABCD...)) Suppress:("=") Group:(Combine:({{W:(ABCD...) | <SP><TAB>}}...))})}, found ':' (at char 41), (line:4, col:13)
See from setDebug value grammar ZeroOrMore is getting the tokens from next line [[['Argument'], ['Name']]]
I tried LineEnd() and other tricks but none works.
Any idea on how to deal with ZeroOrMore to stop on LineEnd() or without special cases?
NOTE: Real output can be retrieved using:
env = os.environ.copy()
env['LANG'] = 'C'
data = check_output(
['pactl', 'list'], universal_newlines=True, env=env)
indentedBlock is not the easiest pyparsing element to work with. But there are a few things that you are doing that are getting in your way.
To debug this, I broke down some of your more complex expressions, use setName() to give them names, and then added .setDebug(). Like this:
identifier = Word(alphas, alphanums+"-_.").setName("identifier").setDebug()
This will tell pyparsing to output a message whenever this expression is about to be matched, if it matched successfully, or if not, the exception that was raised.
Match identifier at loc 1(2,1)
Matched identifier -> ['Module']
Match identifier at loc 15(3,5)
Matched identifier -> ['Argument']
Match identifier at loc 15(3,5)
Matched identifier -> ['Argument']
Match identifier at loc 23(3,13)
Exception raised:Expected identifier, found ':' (at char 23), (line:3, col:13)
It looks like these expressions are messing up the indentedBlock matching, by processing whitespace that should be indentation space:
Combine(OneOrMore(Word(alphanums+'-"/.')|White(' \t')))
The " character in the Word and the whitespace lead me to believe you are trying to match quoted strings. I replaced this expression with:
Combine(OneOrMore(Word(alphas, alphanums+'-/.') | quotedString))
You also need to take care not to read past the end of the line, or you'll also mess up the indentedBlock indentation tracking. I added this expression for a newline at the top:
NL = LineEnd()
and then used it as the stopOn argument to OneOrMore and ZeroOrMore:
prop_val_value = Combine(OneOrMore(Word(alphas, alphanums+'-/.') | quotedString(), stopOn=NL)).setName("prop_val_value")#.setDebug()
prop_val = Group(identifier + Suppress("=") + Group(prop_val_value)).setName("prop_val")#.setDebug()
Here is the parser I ended up with:
indentStack = [1]
stmt = Forward()
NL = LineEnd()
identifier = Word(alphas, alphanums+"-_.").setName("identifier").setDebug()
sect_def = Group(Group(identifier) + Suppress("#") + Group(Word(nums))).setName("sect_def")#.setDebug()
inner_section = indentedBlock(stmt, indentStack)
section = (sect_def + inner_section)
#~ value = Group(Group(Combine(OneOrMore(identifier|White(' ')))) + Suppress(":") + Group(Combine(ZeroOrMore(Word(alphanums+'-/=_".')|White(' ', max=1))))).setDebug()
value_label = originalTextFor(OneOrMore(identifier)).setName("value_label")#.setDebug()
value = Group(value_label
+ Suppress(":")
+ Optional(~NL + Group(Combine(ZeroOrMore(Word(alphanums+'-/=_.') | quotedString(), stopOn=NL))))).setName("value")#.setDebug()
prop_name = Literal("Properties:")
prop_section = indentedBlock(stmt, indentStack)
#~ prop_val = Group(Group(identifier) + Suppress("=") + Group(Combine(OneOrMore(Word(alphanums+'-"/.')|White(' \t')))))
prop_val_value = Combine(OneOrMore(Word(alphas, alphanums+'-/.') | quotedString(), stopOn=NL)).setName("prop_val_value")#.setDebug()
prop_val = Group(identifier + Suppress("=") + Group(prop_val_value)).setName("prop_val")#.setDebug()
prop = (prop_name + prop_section).setName("prop")#.setDebug()
stmt << ( section | prop | value | prop_val )
Which gives this:
[[['Module'], ['6']],
[[['Argument']],
[['Name', ['module-alsa-card']]],
[['Usage counter', ['0']]],
['Properties:',
[[['module.author', ['"Lennart Poettering"']]],
[['module.description', ['"ALSA Card"']]],
[['module.version', ['"14.0-rebootstrapped"']]]]]]]

Splitting a string for printing

I need to print some headers around some strings, you can see it working fine here, although if the string is really long I need to split it then print a much longer header.
+===================================================+
| Running: sdt_test |
| Skipping:inquiry/"Inq VPD C0" mem/"Maint In Cmnd" |
+===================================================+
sh: /net/flanders/export/ws/ned/proto/bin/sdt_test: No such file or directory
+=====================+
| Running: dtd_tester |
+=====================+
sh: /net/flanders/export/ws/ned/proto/bin/dtd_tester: No such file or directory
+===============+
| Running: pssm |
+===============+
sh: /net/flanders/export/ws/ned/proto/bin/pssm: No such file or directory
+==============+
| Running: psm |
+==============+
sh: /net/flanders/export/ws/ned/proto/bin/psm: No such file or directory
+===============================================================================================================================================================================================================================================================================================================================================+
| Running: ssm |
| Skipping:"Secondary Subset Manager Tests"/"SSSM_3 Multi Sequence" "Secondary Subset Manager Tests"/"SSSM_2 Steady State" "Secondary Subset Manager Tests"/"SSSM_4 Test Abort" "Secondary Subset Manager Tests"/"SSSM_6 Test extend" "Secondary Subset Manager Tests"/"SSSM_9 exceptions" "Secondary Subset Manager Tests"/"SSSM_11 failed io" |
+===============================================================================================================================================================================================================================================================================================================================================+
It appears fine there, although the SSM test, I would like split up on a certain amount of characters, maybe 100 or just on the whitespace between suites.
I'm really not too sure on how to do this, this is the code that currently does it.
#calculate lengths to make sure header is correct length
l1 = len(x)
l2 = len(y)
skip = False
if 'disable=' in test and 'disable="*"' not in test:
skip = True
#if entire test suite is to be disabled or not run
if disable:
headerBreak ="+" + "="*(l1+12) + "+"
print headerBreak
print "| Skipping: %s |" % x
#if the test suite will be executed
else:
if skip == False:
l2 = 0
headerBreak = "+" + "="*(max(l1,l2)+11) + "+"
print headerBreak
print "| Running: %s" % x, ' '*(l2-l1)+ '|'
#if some suites are disabled but some are still running
if skip:
print "| Skipping:%s |" % y
print headerBreak
sys.stdout.flush()
You can use the textwrap module to simplify this
For example if the max width was 44
>>> max_width = 44
>>> header='''Skipping:"Secondary Subset Manager Tests"/"SSSM_3 Multi Sequence" "Secondary Subset Manager Tests"/"SSSM_2 Steady State" "Secondary Subset Manager Tests"/"SSSM_4 Test Abort" "Secondary Subset Manager Tests"/"SSSM_6 Test extend" "Secondary Subset Manager Tests"/"SSSM_9 exceptions" "Secondary Subset Manager Tests"/"SSSM_11 failed io"'''
>>> h = ["Running: ssm"] + textwrap.wrap(header, width=max_width-4)
>>> maxh = len(max(h, key=len))
>>> print "+=" + "="*maxh + "=+"
+==========================================+
>>> for i in h:
... print "| " + i.ljust(maxh) + " |"...
| Running: ssm |
| Skipping:"Secondary Subset Manager |
| Tests"/"SSSM_3 Multi Sequence" |
| "Secondary Subset Manager Tests"/"SSSM_2 |
| Steady State" "Secondary Subset Manager |
| Tests"/"SSSM_4 Test Abort" "Secondary |
| Subset Manager Tests"/"SSSM_6 Test |
| extend" "Secondary Subset Manager |
| Tests"/"SSSM_9 exceptions" "Secondary |
| Subset Manager Tests"/"SSSM_11 failed |
| io" |
>>> print "+=" + "="*maxh + "=+"
+==========================================+

mysql-python fetchrow brings: TypeError: 'long' object is not callable

I got a table:
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| Benutzer | varchar(50) | YES | | NULL | |
| Confirmed | tinyint(1) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
with one entry!
If I execute on the mysql console in a shell:
select Benutzer from UserConfirm where Benutzer = '\{\'gid\'\:\ \'tamer\'\,\ \'uid\'\:\ \'tamer\'\}'
it works!
At mysql-python there comes the errormessage:
TypeError: 'long' object is not callable
What did I make wrong?!
Here is my python code:
cursor = self.__db.cursor().execute('select * from UserConfirm where Benutzer = \'' + ds + '\'')
return cursor().fetchrow()
For any advice, I would kindly thank you.
The problem is that you are not storing the cursor object, just the return value of execute, which is not the cursor, it should be:
cursor = self.__db.cursor()
cursor.execute('select * from UserConfirm where Benutzer = \'' + ds + '\'')
return cursor.fetchone()
Note that I assume your line cursor().fetchrow() is a typo and you meant cursor.fetchrow().
Not knowing mysql-python myself, from the error I can assume cursor.execute is returning the number of rows or an error code, not the cursor itself.
Try the following instead:
cursor = self.__db.cursor()
cursor.execute('select * from UserConfirm where Benutzer = \'' + ds + '\'')
return cursor.fetchrow()

Python: Invalid Syntax with test data using Pyparser

Using pyparser, I am trying to create a very simple parser for the S-Expression language. I have written a very small grammar.
Here is my code:
from pyparsing import *
alphaword = Word(alphas)
integer = Word(nums)
sexp = Forward()
LPAREN = Suppress("(")
RPAREN = Suppress(")")
sexp << ( alphaword | integer | ( LPAREN + ZeroOrMore(sexp) + RPAREN)
tests = """\
red
100
( red 100 blue )
( green ( ( 1 2 ) mauve ) plaid () ) """.splitlines()
for t in tests:
print t
print sexp.parseString(t)
print
While looking at examples of this code it seems that everything is fine, however when running i get a syntax error for this line
tests = """\
^
I don't understand it. I would be grateful for any help
parentheses on a previous line are not closed.
sexp << ( alphaword | integer | ( LPAREN + ZeroOrMore(sexp) + RPAREN)
Needs more )'s

Categories

Resources