Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
trs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
trs
Commits
bb8c1c91
Commit
bb8c1c91
authored
Dec 11, 2011
by
Sander Mathijs van Veen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented expression preprocessor and 'graph' statement.
parent
24f62cbb
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
117 additions
and
42 deletions
+117
-42
external/graph_drawing
external/graph_drawing
+1
-1
external/pybison
external/pybison
+1
-1
src/parser.py
src/parser.py
+115
-40
No files found.
graph_drawing
@
003a9e25
Subproject commit
4d65a52b8ba0f0ad1843cb5535a485ff372317a3
Subproject commit
003a9e2536ed7d899b570f07d7d6a0ce60c5f155
pybison
@
eb1d1da4
Subproject commit
2ae8c15dba13faba38e1a3d1a711cf6d24395a5a
Subproject commit
eb1d1da4c21cc3f48cabe19485381e3f7e80f279
src/parser.py
View file @
bb8c1c91
...
...
@@ -39,8 +39,8 @@ class Parser(BisonParser):
# of tokens of the lex script.
tokens
=
[
'NUMBER'
,
'IDENTIFIER'
,
'PLUS'
,
'MINUS'
,
'TIMES'
,
'DIVIDE'
,
'POW'
,
'LPAREN'
,
'RPAREN'
,
'COMMA'
,
'CONCAT_POW'
,
'NEWLINE'
,
'QUIT'
,
'RAISE'
]
'LPAREN'
,
'RPAREN'
,
'COMMA'
,
#
'CONCAT_POW',
'NEWLINE'
,
'QUIT'
,
'RAISE'
,
'GRAPH'
]
# ------------------------------
# precedences
...
...
@@ -71,6 +71,64 @@ class Parser(BisonParser):
except
EOFError
:
return
''
def
hook_read
(
self
,
data
):
"""
This hook will be called when the read() method returned. The data
argument points to the data read by the read() method. This hook
function should return the data to be used by the parser.
"""
import
re
# TODO: remove this quick preprocesing hack. This hack enabled
# concatenated expressions, since the grammar currently does not
# support those. This workaround will replace:
# - ")(" with ")*(".
# - "a(" with "a*(".
# - ")a" with ")*a".
# - "ab" with "a*b".
# - "4a" with "4*a".
# - "a4" with "a^4".
pattern
=
(
'(?:(
\
))
\
s*(
\
()
'
# match: )(
+ '
|
([
a
-
z0
-
9
])
\
s
*
(
\
()
' # match: a(
+ '
|
(
\
))
\
s
*
([
a
-
z0
-
9
])
' # match: )a
+ '
|
([
a
-
z
])
\
s
*
([
a
-
z
]
+
)
' # match: ab
+ '
|
([
0
-
9
])
\
s
*
([
a
-
z
])
' # match: 4a
+ '
|
([
a
-
z
])
\
s
*
([
0
-
9
]))
') # match: a4
def preprocess_data(match):
left, right = filter(None, match.groups())
# Filter words (otherwise they will be preprocessed as well)
if left + right in ['
graph
', '
raise
']:
return left + right
# If all characters on the right are numbers. e.g. "a4", the
# expression implies exponentiation. Make sure ")4" is not
# converted into an exponentiation, because that'
s
multipliciation
.
if
left
!=
')'
\
and
all
(
map
(
lambda
x
:
48
<=
ord
(
x
)
<
58
,
list
(
right
))):
return
'%s^%s'
%
(
left
,
right
)
# match: ab | abc | abcd (where left = "a")
return
'*'
.
join
([
left
]
+
list
(
right
))
# Iteratively replace all matches.
while
True
:
data_after
=
re
.
sub
(
pattern
,
preprocess_data
,
data
)
if
data
==
data_after
:
break
if
self
.
verbose
:
print
'hook_read() modified the input data:'
print
'before:'
,
data
.
replace
(
'
\
n
'
,
'
\
\
n'
)
print
'after :'
,
data_after
.
replace
(
'
\
n
'
,
'
\
\
n'
)
data
=
data_after
return
data
# ---------------------------------------------------------------
# These methods are the python handlers for the bison targets.
# (which get called by the bison code each time the corresponding
...
...
@@ -103,14 +161,27 @@ class Parser(BisonParser):
"""
line : NEWLINE
| exp NEWLINE
| debug NEWLINE
| RAISE NEWLINE
"""
if
option
==
1
:
if
option
in
[
1
,
2
]
:
return
values
[
0
]
if
option
==
2
:
if
option
==
3
:
raise
RuntimeError
(
'on_line: exception raised'
)
def
on_debug
(
self
,
target
,
option
,
names
,
values
):
"""
debug : GRAPH exp
"""
if
option
==
0
:
print
generate_graph
(
values
[
1
])
return
values
[
1
]
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
def
on_exp
(
self
,
target
,
option
,
names
,
values
):
"""
exp : NUMBER
...
...
@@ -118,8 +189,8 @@ class Parser(BisonParser):
| LPAREN exp RPAREN
| unary
| binary
| concat
"""
# | concat
if
option
==
0
:
# rule: NUMBER
# TODO: A bit hacky, this achieves long integers and floats.
...
...
@@ -132,9 +203,12 @@ class Parser(BisonParser):
if
option
==
2
:
# rule: LPAREN exp RPAREN
return
values
[
1
]
if
option
in
[
3
,
4
,
5
]:
# rule: unary | binary | concat
if
option
in
[
3
,
4
]:
# rule: unary | binary
return
values
[
0
]
#if option in [3, 4, 5]: # rule: unary | binary | concat
# return values[0]
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
...
...
@@ -179,39 +253,39 @@ class Parser(BisonParser):
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
def
on_concat
(
self
,
option
,
target
,
names
,
values
):
"""
concat : exp IDENTIFIER
| exp NUMBER
| exp LPAREN exp RPAREN
| exp CONCAT_POW
| CONCAT_POW
"""
if
option
in
[
0
,
1
]:
# rule: exp IDENTIFIER | exp NUMBER
# example: xy -> x*y
# example: (x)4 -> x*4
val
=
int
(
values
[
1
])
if
option
==
1
else
values
[
1
]
return
Node
(
'*'
,
*
(
combine
(
'*'
,
values
[
0
])
+
[
Leaf
(
val
)]))
if
option
==
2
:
# rule: exp LPAREN exp RPAREN
# example: x(y) -> x*(y)
return
Node
(
'*'
,
*
(
combine
(
'*'
,
values
[
0
])
+
combine
(
'*'
,
values
[
2
])))
if
option
==
3
:
# example: xy4 -> x*y^4
identifier
,
exponent
=
list
(
values
[
1
])
node
=
Node
(
'^'
,
Leaf
(
identifier
),
Leaf
(
int
(
exponent
)))
return
Node
(
'*'
,
values
[
0
],
node
)
if
option
==
4
:
# example: x4 -> x^4
identifier
,
exponent
=
list
(
values
[
0
])
return
Node
(
'^'
,
Leaf
(
identifier
),
Leaf
(
int
(
exponent
)))
raise
BisonSyntaxError
(
'Unsupported option %d in target "%s".'
%
(
option
,
target
))
# pragma: nocover
#
def on_concat(self, option, target, names, values):
#
"""
# concat : exp IDENTIFIER %prec TIMES
# | exp NUMBER %prec TIMES
# | exp LPAREN exp RPAREN %prec TIMES
# | exp CONCAT_POW %prec TIMES
#
| CONCAT_POW
#
"""
#
if option in [0, 1]: # rule: exp IDENTIFIER | exp NUMBER
#
# example: xy -> x*y
#
# example: (x)4 -> x*4
#
val = int(values[1]) if option == 1 else values[1]
#
return Node('*', *(combine('*', values[0]) + [Leaf(val)]))
#
if option == 2: # rule: exp LPAREN exp RPAREN
#
# example: x(y) -> x*(y)
#
return Node('*', *(combine('*', values[0])
#
+ combine('*', values[2])))
#
if option == 3:
#
# example: xy4 -> x*y^4
#
identifier, exponent = list(values[1])
#
node = Node('^', Leaf(identifier), Leaf(int(exponent)))
#
return Node('*', values[0], node)
#
if option == 4:
#
# example: x4 -> x^4
#
identifier, exponent = list(values[0])
#
return Node('^', Leaf(identifier), Leaf(int(exponent)))
#
raise BisonSyntaxError('Unsupported option %d in target "%s".'
#
% (option, target)) # pragma: nocover
# -----------------------------------------
# raw lex script, verbatim here
...
...
@@ -230,11 +304,11 @@ class Parser(BisonParser):
#define YY_INPUT(buf,result,max_size) { \
(*py_input)(py_parser, buf, &result, max_size); \
}
/*[a-zA-Z][0-9]+ { returntoken(CONCAT_POW); }*/
%}
%%
[a-zA-Z][0-9]+ { returntoken(CONCAT_POW); }
[0-9]+ { returntoken(NUMBER); }
[a-zA-Z] { returntoken(IDENTIFIER); }
"(" { returntoken(LPAREN); }
...
...
@@ -247,6 +321,7 @@ class Parser(BisonParser):
"," { returntoken(COMMA); }
"quit" { printf("lex: got QUIT\n"); yyterminate(); returntoken(QUIT); }
"raise" { returntoken(RAISE); }
"graph" { returntoken(GRAPH); }
[ \t\v\f] {}
[\n] {yylineno++; returntoken(NEWLINE); }
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment