Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
A
arpeggio-gm
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
2
Merge Requests
2
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
郭家华
arpeggio-gm
Commits
1c76b784
Commit
1c76b784
authored
Aug 07, 2014
by
Igor Dejanovic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Various changes on textx and pyflies languages.
parent
ab924aea
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
156 additions
and
104 deletions
+156
-104
textx.py
arpeggio/textx.py
+138
-100
experiment.pf
examples/textx/experiment.pf
+1
-1
pyflies.tx
examples/textx/pyflies.tx
+17
-3
No files found.
arpeggio/textx.py
View file @
1c76b784
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
from
collections
import
namedtuple
from
collections
import
namedtuple
from
arpeggio
import
StrMatch
,
Optional
,
ZeroOrMore
,
OneOrMore
,
Sequence
,
\
from
arpeggio
import
StrMatch
,
Optional
,
ZeroOrMore
,
OneOrMore
,
Sequence
,
\
OrderedChoice
,
RegExMatch
,
EOF
,
\
OrderedChoice
,
RegExMatch
,
NoMatch
,
EOF
,
\
SemanticAction
,
ParserPython
,
Combine
,
Parser
,
SemanticActionSingleChild
,
\
SemanticAction
,
ParserPython
,
Combine
,
Parser
,
SemanticActionSingleChild
,
\
SemanticActionBodyWithBraces
SemanticActionBodyWithBraces
from
arpeggio.export
import
PMDOTExporter
,
PTDOTExporter
from
arpeggio.export
import
PMDOTExporter
,
PTDOTExporter
...
@@ -42,7 +42,7 @@ def repeat_operator(): return ['*', '?', '+']
...
@@ -42,7 +42,7 @@ def repeat_operator(): return ['*', '?', '+']
def
assignment
():
return
attribute
,
assignment_op
,
assignment_rhs
def
assignment
():
return
attribute
,
assignment_op
,
assignment_rhs
def
attribute
():
return
ident
def
attribute
():
return
ident
def
assignment_op
():
return
[
"="
,
"*="
,
"+="
,
"?="
]
def
assignment_op
():
return
[
"="
,
"*="
,
"+="
,
"?="
]
def
assignment_rhs
():
return
[
rule_ref
,
list_match
,
terminal_match
]
def
assignment_rhs
():
return
[
rule_ref
,
list_match
,
terminal_match
,
bracketed_choice
]
# Match
# Match
def
match
():
return
[
terminal_match
,
list_match
,
rule_ref
]
def
match
():
return
[
terminal_match
,
list_match
,
rule_ref
]
...
@@ -57,8 +57,8 @@ def list_separator(): return terminal_match
...
@@ -57,8 +57,8 @@ def list_separator(): return terminal_match
# Rule reference
# Rule reference
def
rule_ref
():
return
[
rule_match
,
rule_link
]
def
rule_ref
():
return
[
rule_match
,
rule_link
]
def
rule_match
():
return
ident
def
rule_match
():
return
ident
def
rule_link
():
return
'['
,
rule_
choic
e
,
']'
def
rule_link
():
return
'['
,
rule_
nam
e
,
']'
def
rule_choice
():
return
rule_name
,
ZeroOrMore
(
'|'
,
rule_name
)
#
def rule_choice(): return rule_name, ZeroOrMore('|', rule_name)
def
rule_name
():
return
ident
def
rule_name
():
return
ident
def
ident
():
return
_
(
r'\w+'
)
def
ident
():
return
_
(
r'\w+'
)
...
@@ -70,6 +70,11 @@ def comment_line(): return _(r'//.*$')
...
@@ -70,6 +70,11 @@ def comment_line(): return _(r'//.*$')
def
comment_block
():
return
_
(
r'/\*(.|\n)*?\*/'
)
def
comment_block
():
return
_
(
r'/\*(.|\n)*?\*/'
)
# Special rules - primitive types
ID
=
_
(
r'[^\d\W]\w*\b'
,
rule
=
'ID'
,
root
=
True
)
INT
=
_
(
r'[-+]?[0-9]+'
,
rule
=
'INT'
,
root
=
True
)
FLOAT
=
_
(
r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?'
,
'FLOAT'
,
root
=
True
)
STRING
=
_
(
r'("[^"]*")|(\'[^\']*\')'
,
'STRING'
,
root
=
True
)
class
RuleMatchCrossRef
(
object
):
class
RuleMatchCrossRef
(
object
):
"""Helper class used for cross reference resolving."""
"""Helper class used for cross reference resolving."""
...
@@ -78,7 +83,16 @@ class RuleMatchCrossRef(object):
...
@@ -78,7 +83,16 @@ class RuleMatchCrossRef(object):
self
.
position
=
position
self
.
position
=
position
class
TextXSemanticError
(
Exception
):
# TextX Exceptions
class
TextXError
(
Exception
):
pass
class
TextXSemanticError
(
TextXError
):
pass
class
TextXSyntaxError
(
TextXError
):
pass
pass
...
@@ -94,11 +108,18 @@ class TextXModelSA(SemanticAction):
...
@@ -94,11 +108,18 @@ class TextXModelSA(SemanticAction):
"""
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
TextXLanguageParser
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
TextXLanguageParser
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
parser_model
=
Sequence
(
nodes
=
children
[:],
rule
=
'model'
,
root
=
True
)
# By default first rule is starting rule
self
.
parser_model
=
children
[
0
]
self
.
comments_model
=
parser
.
_peg_rules
.
get
(
'__comment'
,
None
)
self
.
comments_model
=
parser
.
_peg_rules
.
get
(
'__comment'
,
None
)
self
.
debug
=
parser
.
debug
def
_parse
(
self
):
def
_parse
(
self
):
return
self
.
parser_model
.
parse
(
self
)
try
:
return
self
.
parser_model
.
parse
(
self
)
except
NoMatch
as
e
:
raise
TextXSyntaxError
(
str
(
e
))
textx_parser
=
TextXLanguageParser
()
textx_parser
=
TextXLanguageParser
()
...
@@ -152,98 +173,113 @@ class TextXModelSA(SemanticAction):
...
@@ -152,98 +173,113 @@ class TextXModelSA(SemanticAction):
return
textx_parser
return
textx_parser
textx_model
.
sem
=
TextXModelSA
()
class
MetaClassSA
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
rule_name
,
rule
=
children
# Do some name mangling for comment rule
# to prevent refererencing from other rules
if
rule_name
.
lower
()
==
"comment"
:
rule_name
=
"__comment"
parser
.
_peg_rules
[
rule_name
]
=
rule
return
rule
class
MetaClassNameSA
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
class
Meta
(
object
):
"""Dynamic metaclass."""
pass
name
=
str
(
node
)
cls
=
Meta
cls
.
__name__
=
name
# TODO: Attributes and inheritance
parser
.
_metaclasses
[
name
]
=
cls
parser
.
_current_metaclass
=
cls
# First rule will be the root of the meta-model
if
not
parser
.
root_rule_name
:
parser
.
root_rule_name
=
name
return
name
class
SequenceSA
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
return
Sequence
(
nodes
=
children
[:])
class
ChoiceSA
(
SemanticAction
):
def
first_pass
(
self
,
parser
,
node
,
children
):
return
OrderedChoice
(
nodes
=
children
[:])
class
AssignmentSA
(
SemanticAction
):
def
metaclass_SA
(
parser
,
node
,
children
):
def
first_pass
(
self
,
parser
,
node
,
children
):
rule_name
,
rule
=
children
#TODO: Register assignment on metaclass
rule
.
rule
=
rule_name
rule
.
root
=
True
# Do some name mangling for comment rule
# to prevent refererencing from other rules
if
rule_name
.
lower
()
==
"comment"
:
rule_name
=
"__comment"
parser
.
_peg_rules
[
rule_name
]
=
rule
return
rule
metaclass
.
sem
=
metaclass_SA
def
metaclass_name_SA
(
parser
,
node
,
children
):
class
Meta
(
object
):
"""Dynamic metaclass."""
pass
name
=
str
(
node
)
cls
=
Meta
cls
.
__name__
=
name
# TODO: Attributes and inheritance
parser
.
_metaclasses
[
name
]
=
cls
parser
.
_current_metaclass
=
cls
# First rule will be the root of the meta-model
if
not
parser
.
root_rule_name
:
parser
.
root_rule_name
=
name
return
name
metaclass_name
.
sem
=
metaclass_name_SA
def
sequence_SA
(
parser
,
node
,
children
):
return
Sequence
(
nodes
=
children
[:])
sequence
.
sem
=
sequence_SA
def
choice_SA
(
parser
,
node
,
children
):
return
OrderedChoice
(
nodes
=
children
[:])
choice
.
sem
=
choice_SA
def
assignment_SA
(
parser
,
node
,
children
):
#TODO: Register assignment on metaclass
# Implement semantic for addition
rhs
=
children
[
2
]
op
=
children
[
1
]
if
op
==
'+='
:
return
OneOrMore
(
nodes
=
[
rhs
])
elif
op
==
'*='
:
return
ZeroOrMore
(
nodes
=
[
rhs
])
elif
op
==
'?='
:
return
Optional
(
nodes
=
[
rhs
])
else
:
return
children
[
2
]
return
children
[
2
]
assignment
.
sem
=
assignment_SA
class
ExprSA
(
SemanticAction
):
def
expr_SA
(
parser
,
node
,
children
):
def
first_pass
(
self
,
parser
,
node
,
children
):
if
children
[
1
]
==
'?'
:
if
children
[
1
]
==
'?'
:
return
Optional
(
nodes
=
[
children
[
0
]])
return
Optional
(
nodes
=
[
children
[
0
]])
elif
children
[
1
]
==
'*'
:
elif
children
[
1
]
==
'*'
:
return
ZeroOrMore
(
nodes
=
[
children
[
0
]])
return
ZeroOrMore
(
nodes
=
[
children
[
0
]])
elif
children
[
1
]
==
'+'
:
elif
children
[
1
]
==
'+'
:
return
OneOrMore
(
nodes
=
[
children
[
0
]])
return
OneOrMore
(
nodes
=
[
children
[
0
]])
else
:
else
:
TextXSemanticError
(
'Unknown repetition operand "{}" at {}'
\
TextXSemanticError
(
'Unknown repetition operand "{}" at {}'
\
.
format
(
children
[
1
],
str
(
parser
.
pos_to_linecol
(
node
[
1
]
.
position
))))
.
format
(
children
[
1
],
str
(
parser
.
pos_to_linecol
(
node
[
1
]
.
position
))))
expr
.
sem
=
expr_SA
def
str_match_SA
(
parser
,
node
,
children
):
class
StrMatchSA
(
SemanticAction
):
return
StrMatch
(
children
[
0
],
ignore_case
=
parser
.
ignore_case
)
def
first_pass
(
self
,
parser
,
node
,
children
):
str_match
.
sem
=
str_match_SA
return
StrMatch
(
children
[
0
],
ignore_case
=
parser
.
ignore_case
)
def
re_match_SA
(
parser
,
node
,
children
):
to_match
=
children
[
0
]
class
REMatchSA
(
SemanticAction
):
regex
=
RegExMatch
(
to_match
,
ignore_case
=
parser
.
ignore_case
)
def
first_pass
(
self
,
parser
,
node
,
children
):
try
:
to_match
=
children
[
0
]
print
(
"TOMATCH:"
,
to_match
)
regex
=
RegExMatch
(
to_match
,
ignore_case
=
parser
.
ignore_case
)
regex
.
compile
()
regex
.
compile
()
return
regex
except
Exception
as
e
:
raise
TextXSyntaxError
(
"{} at {}"
.
format
(
str
(
e
),
\
str
(
parser
.
pos_to_linecol
(
node
[
1
]
.
position
))))
class
RuleMatchSA
(
SemanticAction
):
return
regex
def
first_pass
(
self
,
parser
,
node
,
children
):
re_match
.
sem
=
re_match_SA
return
RuleMatchCrossRef
(
str
(
node
),
node
.
position
)
def
rule_match_SA
(
parser
,
node
,
children
):
return
RuleMatchCrossRef
(
str
(
node
),
node
.
position
)
rule_match
.
sem
=
rule_match_SA
textx_model
.
sem
=
TextXModelSA
()
metaclass
.
sem
=
MetaClassSA
()
def
rule_link_SA
(
parser
,
node
,
children
):
metaclass_name
.
sem
=
MetaClassNameSA
()
# TODO: In analisys during model parsing this will be a link to some other object
sequence
.
sem
=
SequenceSA
()
# identified by target metaclass ID
choice
.
sem
=
ChoiceSA
()
return
ID
rule_link
.
sem
=
rule_link_SA
def
list_match_SA
(
parser
,
node
,
children
):
if
len
(
children
)
==
1
:
return
children
[
0
]
else
:
match
=
children
[
0
]
separator
=
children
[
1
]
return
Sequence
(
nodes
=
[
children
[
0
],
ZeroOrMore
(
nodes
=
Sequence
(
nodes
=
[
separator
,
match
]))])
list_match
.
sem
=
list_match_SA
# Default actions
bracketed_choice
.
sem
=
SemanticActionSingleChild
()
bracketed_choice
.
sem
=
SemanticActionSingleChild
()
expr
.
sem
=
ExprSA
()
str_match
.
sem
=
StrMatchSA
()
re_match
.
sem
=
REMatchSA
()
rule_match
.
sem
=
RuleMatchSA
()
def
get_parser
(
language_def
,
ignore_case
=
True
,
debug
=
False
):
def
get_parser
(
language_def
,
ignore_case
=
True
,
debug
=
False
):
...
@@ -254,11 +290,10 @@ def get_parser(language_def, ignore_case=True, debug=False):
...
@@ -254,11 +290,10 @@ def get_parser(language_def, ignore_case=True, debug=False):
# This is used during parser construction phase.
# This is used during parser construction phase.
parser
.
_metaclasses
=
{}
parser
.
_metaclasses
=
{}
parser
.
_peg_rules
=
{
parser
.
_peg_rules
=
{
# Special rules - primitive types
'ID'
:
ID
,
'ID'
:
_
(
r'[^\d\W]\w*\b'
),
'INT'
:
INT
,
'INT'
:
_
(
r'[-+]?[0-9]+'
),
'FLOAT'
:
FLOAT
,
'FLOAT'
:
_
(
r'[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?'
),
'STRING'
:
STRING
,
'STRING'
:
_
(
r'("[^"]*")|(\'[^\']*\')'
)
}
}
for
regex
in
parser
.
_peg_rules
.
values
():
for
regex
in
parser
.
_peg_rules
.
values
():
regex
.
compile
()
regex
.
compile
()
...
@@ -266,7 +301,10 @@ def get_parser(language_def, ignore_case=True, debug=False):
...
@@ -266,7 +301,10 @@ def get_parser(language_def, ignore_case=True, debug=False):
parser
.
root_rule_name
=
None
parser
.
root_rule_name
=
None
# Parse language description with TextX parser
# Parse language description with TextX parser
parse_tree
=
parser
.
parse
(
language_def
)
try
:
parse_tree
=
parser
.
parse
(
language_def
)
except
NoMatch
as
e
:
raise
TextXSyntaxError
(
str
(
e
))
# Construct new parser based on the given language description.
# Construct new parser based on the given language description.
# This parser will have semantic actions in place to create
# This parser will have semantic actions in place to create
...
...
examples/textx/experiment.pf
View file @
1c76b784
...
@@ -49,7 +49,7 @@ experiment {
...
@@ -49,7 +49,7 @@ experiment {
# Variable_name, type, optional label
# Variable_name, type, optional label
# Type can be: str, int, float or enumerated list
# Type can be: str, int, float or enumerated list
subject {
subject {
full_name str "First and last name"
full_name str
ing
"First and last name"
age int
age int
gender [Male, Female] "Gender"
gender [Male, Female] "Gender"
}
}
...
...
examples/textx/pyflies.tx
View file @
1c76b784
/*
/*
This is a TextX
defini
tion of pyFlies DSL for Reaction Time test
This is a TextX
specifica
tion of pyFlies DSL for Reaction Time test
experiments definition.
experiments definition.
Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
Author: Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
Copyright: (c) 2014 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
Copyright: (c) 2014 Igor R. Dejanovic <igor DOT dejanovic AT gmail DOT com>
...
@@ -21,7 +21,7 @@ TestType:
...
@@ -21,7 +21,7 @@ TestType:
;
;
TestParam:
TestParam:
name=ID TestParamValue
label=TestParamLabel?
name=ID TestParamValue
;
;
TestParamValue:
TestParamValue:
...
@@ -34,7 +34,7 @@ TestParamLabel:
...
@@ -34,7 +34,7 @@ TestParamLabel:
Block:
Block:
Intro|Test|Sequence|Randomize
Intro|Test|Sequence|Randomize
|Subject
;
;
Experiment:
Experiment:
...
@@ -65,6 +65,20 @@ Intro:
...
@@ -65,6 +65,20 @@ Intro:
/====*/
/====*/
;
;
Subject:
'subject' '{'
attribute+=SubjectAttribute
'}'
;
SubjectAttribute:
name=ID type=("int"|"string"|"float"|Enum) label=STRING?
;
Enum:
'[' values+={ID ','} ']'
;
// Special rule for comments
// Special rule for comments
Comment:
Comment:
/#.*$/
/#.*$/
...
...
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