Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
OpenGEODE
Commits
c2762c46
Commit
c2762c46
authored
Mar 09, 2014
by
Maxime Perrotin
Browse files
Parser bugfix (type resolution)
parent
24924186
Changes
5
Show whitespace changes
Inline
Side-by-side
ogParser.py
View file @
c2762c46
...
...
@@ -295,13 +295,14 @@ def is_constant(var):
def
fix_special_operators
(
op_name
,
expr_list
,
context
):
''' Verify/fix type of special operators parameters '''
if
op_name
.
lower
()
in
(
'length'
,
'present'
):
if
op_name
.
lower
()
in
(
'length'
,
'present'
,
'abs'
):
if
len
(
expr_list
)
!=
1
:
raise
AttributeError
(
'Only one parameter for the {} operator'
.
format
(
op_name
))
expr
=
expr_list
[
0
]
if
expr
.
exprType
is
UNKNOWN_TYPE
:
expr
.
exprType
=
find_variable
(
expr
.
inputString
,
context
)
# XXX don't use inputString, there can be brackets
# XXX should change type to PrimVariable
basic
=
find_basic_type
(
expr
.
exprType
)
if
op_name
.
lower
()
==
'length'
and
basic
.
kind
!=
'SequenceOfType'
\
...
...
@@ -634,13 +635,10 @@ def find_type(path, context):
it is context-dependent (the name of a variable may conflict with the
name of a enumeration item or a choice determinant)
'''
errors
=
[]
warnings
=
[]
result
=
UNKNOWN_TYPE
assert
len
(
path
)
>
1
,
str
(
path
)
if
not
DV
:
errors
.
append
(
'Dataview is required to process types'
)
return
result
,
errors
,
warnings
raise
AttributeError
(
'Dataview is required to process types'
)
LOG
.
debug
(
'[find_type] '
+
str
(
path
))
# First, find the type of the main element
main
=
path
[
0
]
...
...
@@ -665,17 +663,14 @@ def find_type(path, context):
# with elements being the choice options
param
,
=
path
[
1
].
get
(
'procParams'
)
or
[
None
]
if
not
param
:
errors
.
append
(
'Missing parameter in PRESENT clause'
)
raise
TypeError
(
'Missing parameter in PRESENT clause'
)
else
:
check_type
=
find_variable
(
param
.
inputString
,
context
)
\
if
param
.
exprType
==
UNKNOWN_TYPE
else
\
param
.
exprType
try
:
param_type
=
find_basic_type
(
check_type
)
except
TypeError
as
err
:
errors
.
append
(
'[find_type]'
+
str
(
err
))
if
param_type
.
kind
!=
'ChoiceType'
:
errors
.
append
(
'PRESENT parameter'
raise
TypeError
(
'PRESENT parameter'
' must be a CHOICE type:'
+
str
(
path
))
else
:
result
.
EnumValues
=
param_type
.
Children
...
...
@@ -689,27 +684,23 @@ def find_type(path, context):
# We have more than one element and the first one is of type 'result'
# Iterate over the path to get the type of the last element
for
elem
in
path
[
1
:]:
try
:
basic
=
find_basic_type
(
result
)
except
TypeError
as
err
:
errors
.
append
(
str
(
err
))
return
result
,
errors
,
warnings
if
'procParams'
in
elem
:
# Discard operator parameters: they do not change the type
continue
# Sequence, Choice (case insensitive)
if
basic
.
kind
in
(
'SequenceType'
,
'ChoiceType'
):
if
'index'
in
elem
:
errors
.
append
(
'Element {} cannot have an index'
.
format
(
path
[
0
]))
return
result
,
errors
,
warnings
raise
TypeError
(
'Element {} cannot have an index'
.
format
(
path
[
0
]))
elem_asn1
=
elem
.
replace
(
'_'
,
'-'
).
lower
()
type_idx
=
[
c
for
c
in
basic
.
Children
if
c
.
lower
()
==
elem_asn1
]
if
type_idx
:
result
=
basic
.
Children
[
type_idx
[
0
]].
type
else
:
errors
.
append
(
'Field '
+
elem
+
' not found in expression '
raise
TypeError
(
'Field '
+
elem
+
' not found in expression '
+
'!'
.
join
(
path
))
result
=
UNKNOWN_TYPE
break
...
...
@@ -728,18 +719,14 @@ def find_type(path, context):
elif
basic
.
kind
.
endswith
(
'StringType'
):
# Can be an index or a substring
if
'index'
in
elem
:
errors
.
append
(
'Index on a string is not supported'
)
raise
TypeError
(
'Index on a string is not supported'
)
elif
'substring'
in
elem
:
# don't change type, returns a string
# XXX Size may differ
pass
else
:
errors
.
append
(
'Expression '
+
'!'
.
join
(
path
)
+
' does not resolve - check field "'
+
str
(
elem
)
+
'"'
)
result
=
UNKNOWN_TYPE
break
return
result
,
errors
,
warnings
raise
TypeError
(
'Incorrect field or index'
)
return
result
def
expression_list
(
root
,
context
):
...
...
@@ -899,15 +886,21 @@ def primary_value(root, context=None):
# If there were parameters or index, try to determine the type of
# the expression
if
isinstance
(
prim
,
ogAST
.
PrimPath
)
and
len
(
prim
.
value
)
>
1
:
prim
.
exprType
,
err
,
warn
=
find_type
(
prim
.
value
,
context
)
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
try
:
prim
.
exprType
=
find_type
(
prim
.
value
,
context
)
except
TypeError
as
err
:
errors
.
append
(
'Type of expression "'
+
get_input_string
(
root
)
+
'" not found: '
+
str
(
err
))
except
AttributeError
as
err
:
LOG
.
debug
(
'[find_types] '
+
str
(
err
))
if
prim
:
prim
.
inputString
=
get_input_string
(
root
)
else
:
prim
=
ogAST
.
PrimPath
()
return
prim
,
errors
,
warnings
def
primary
(
root
,
context
):
''' Process a primary (-/NOT value) '''
warnings
=
[]
...
...
@@ -1020,13 +1013,14 @@ def expression(root, context):
lexer
.
AND
,
lexer
.
IN
):
expr
.
exprType
=
BOOLEAN
elif
root
.
type
==
lexer
.
PLUS
:
#
elif root.type == lexer.PLUS:
# Adjust type constraint upper range with sum of expressions
# Create a new type to store the new constraint
expr
.
exprType
=
type
(
'Plus_Type'
,
(
find_basic_type
(
expr
.
left
.
exprType
),),
{})
expr
.
exprType
.
Max
=
str
(
int
(
expr
.
exprType
.
Max
)
+
int
(
find_basic_type
(
expr
.
right
.
exprType
).
Max
))
# INCORRECT TO DO IT HERE - we must check right and left types FIRST
# expr.exprType = type('Plus_Type',
# (find_basic_type(expr.left.exprType),), {})
# expr.exprType.Max = str(int(find_basic_type(expr.left.exprType).Max) +
# int(find_basic_type(expr.right.exprType).Max))
elif
root
.
type
in
(
lexer
.
PLUS
,
lexer
.
ASTERISK
,
lexer
.
DASH
,
...
...
@@ -1827,7 +1821,7 @@ def procedure_call(root, parent, context):
''' Parse a PROCEDURE CALL (synchronous required interface) '''
# Same as OUTPUT for external procedures
out_ast
=
ogAST
.
ProcedureCall
()
err
,
warn
=
output
(
root
,
parent
,
out_ast
,
context
)
_
,
err
,
warn
=
output
(
root
,
parent
,
out_ast
,
context
)
return
out_ast
,
err
,
warn
...
...
@@ -1871,11 +1865,12 @@ def outputbody(root, context):
return
body
,
errors
,
warnings
def
output
(
root
,
parent
,
out_ast
,
context
):
def
output
(
root
,
parent
,
out_ast
=
None
,
context
=
None
):
''' Parse an OUTPUT : set of asynchronous required interface(s) '''
errors
=
[]
warnings
=
[]
coord
=
False
out_ast
=
out_ast
or
ogAST
.
Output
()
# syntax checker passes no ast
for
child
in
root
.
getChildren
():
if
child
.
type
==
lexer
.
CIF
:
# Get symbol coordinates
...
...
@@ -1901,7 +1896,7 @@ def output(root, parent, out_ast, context):
if
coord
:
errors
=
[[
e
,
[
out_ast
.
pos_x
,
out_ast
.
pos_y
]]
for
e
in
errors
]
warnings
=
[[
w
,
[
out_ast
.
pos_x
,
out_ast
.
pos_y
]]
for
w
in
warnings
]
return
errors
,
warnings
return
out_ast
,
errors
,
warnings
def
alternative_part
(
root
,
parent
,
context
):
...
...
@@ -2134,7 +2129,7 @@ def transition(root, parent, context):
parent
=
t
elif
child
.
type
==
lexer
.
OUTPUT
:
out_ast
=
ogAST
.
Output
()
err
,
warn
=
output
(
child
,
_
,
err
,
warn
=
output
(
child
,
parent
=
parent
,
out_ast
=
out_ast
,
context
=
context
)
...
...
@@ -2176,9 +2171,12 @@ def fix_expression_types(expr, context):
for
side
in
(
'left'
,
'right'
):
# Determine if the expression is a variable
uk_expr
=
getattr
(
expr
,
side
)
if
uk_expr
.
exprType
==
UNKNOWN_TYPE
and
not
uk_expr
.
is_raw
:
if
uk_expr
.
exprType
==
UNKNOWN_TYPE
\
and
isinstance
(
uk_expr
,
ogAST
.
PrimPath
)
\
and
len
(
uk_expr
.
value
)
==
1
:
try
:
exprType
=
find_variable
(
uk_expr
.
inputString
,
context
)
#exprType = find_variable(uk_expr.inputString, context)
exprType
=
find_variable
(
uk_expr
.
value
[
0
],
context
)
setattr
(
expr
,
side
,
ogAST
.
PrimVariable
(
primary
=
uk_expr
))
getattr
(
expr
,
side
).
exprType
=
exprType
except
AttributeError
:
...
...
@@ -2260,11 +2258,14 @@ def fix_expression_types(expr, context):
asn_type
=
find_basic_type
(
expr
.
left
.
exprType
)
field
=
expr
.
right
.
value
[
'choice'
].
replace
(
'_'
,
'-'
)
if
asn_type
.
kind
!=
'ChoiceType'
\
or
field
not
in
asn_type
.
Children
.
keys
():
raise
TypeError
(
'left side must be a valid CHOICE type'
)
or
field
.
lower
()
not
in
[
key
.
lower
()
for
key
in
asn_type
.
Children
.
viewkeys
()]:
raise
TypeError
(
'Field is not valid in CHOICE:'
+
field
)
key
,
=
[
key
for
key
in
asn_type
.
Children
.
viewkeys
()
if
key
.
lower
()
==
field
.
lower
()]
if
expr
.
right
.
value
[
'value'
].
exprType
==
UNKNOWN_TYPE
:
try
:
expected_type
=
asn_type
.
Children
.
get
(
field
).
type
expected_type
=
asn_type
.
Children
.
get
(
key
).
type
except
AttributeError
:
raise
TypeError
(
'Field not found in CHOICE: '
+
field
)
check_expr
=
ogAST
.
ExprAssign
()
...
...
@@ -2613,8 +2614,13 @@ def parseSingleElement(elem='', string=''):
backend_ptr
=
eval
(
elem
)
# Create a dummy process, needed to place context data
context
=
ogAST
.
Process
()
try
:
t
,
semantic_errors
,
warnings
=
backend_ptr
(
root
=
root
,
parent
=
None
,
context
=
context
)
except
AttributeError
:
# Syntax checker has no visibility on variables and types
# so we have to discard exceptions sent by e.g. find_variable
pass
return
(
t
,
syntax_errors
,
semantic_errors
,
warnings
,
context
.
terminators
)
...
...
opengeode.py
View file @
c2762c46
...
...
@@ -1496,8 +1496,10 @@ class OG_MainWindow(QtGui.QMainWindow, object):
if
types
:
self
.
asn1_area
.
text
.
setPlainText
(
'
\n
'
.
join
(
types
))
self
.
asn1_area
.
text
.
try_resize
()
except
IOError
:
LOG
.
warning
(
'ASN.1 file(s) could not be loaded'
)
except
IOError
as
err
:
LOG
.
warning
(
'ASN.1 file(s) could not be loaded : '
+
str
(
err
))
except
AttributeError
:
LOG
.
warning
(
'No AST, check input files'
)
def
vi_command
(
self
):
'''
...
...
tests/regression/test1/og.pr
View file @
c2762c46
...
...
@@ -12,54 +12,56 @@ DCL test Some_Thing;
/* CIF ENDTEXT */
/* CIF START (-252, -114), (100, 50) */
START;
/* CIF TASK (-257, -49), (110, 50) */
TASK test := 5;
/* CIF TASK (-304, 16), (204, 50) */
/* CIF TASK (-284, -49), (164, 53) */
TASK test := 5,
test := abs(-4+1),
test := abs(test);
/* CIF TASK (-304, 19), (204, 50) */
TASK first_msg := 'Say hello first!'
/* CIF COMMENT (-80, 1
6
), (148, 50) */
/* CIF COMMENT (-80, 1
9
), (148, 50) */
COMMENT 'String assignment';
/* CIF TASK (-284, 8
1
), (165, 50) */
/* CIF TASK (-284, 8
4
), (165, 50) */
TASK seq := default_seqof,
seq := {1,2,3}
/* CIF COMMENT (-100, 8
1
), (204, 50) */
/* CIF COMMENT (-100, 8
4
), (204, 50) */
COMMENT 'default_seqof is a constant
defined in the ASN.1 model';
/* CIF TASK (-333, 14
6
), (263, 50) */
/* CIF TASK (-333, 14
9
), (263, 50) */
TASK seq := seq // {4, test} // default_seqof
/* CIF COMMENT (-50, 14
6
), (156, 50) */
/* CIF COMMENT (-50, 14
9
), (156, 50) */
COMMENT 'Concatenate
two SEQUENCE OF';
/* CIF TASK (-270, 21
1
), (137, 50) */
/* CIF TASK (-270, 21
4
), (137, 50) */
TASK 'seq(1) := seq(2)';
/* CIF TASK (-298, 27
6
), (193, 50) */
/* CIF TASK (-298, 27
9
), (193, 50) */
TASK seq := seq(1,2) // seq(4,5)
/* CIF COMMENT (-86, 27
6
), (166, 50) */
/* CIF COMMENT (-86, 27
9
), (166, 50) */
COMMENT 'Remove 3rd element';
/* CIF DECISION (-254, 34
1
), (104, 70) */
/* CIF DECISION (-254, 34
4
), (104, 70) */
DECISION test in seq
/* CIF COMMENT (-130, 35
6
), (170, 39) */
/* CIF COMMENT (-130, 35
9
), (170, 39) */
COMMENT 'Test the "in" operator';
/* CIF ANSWER (-344, 43
1
), (100, 35) */
/* CIF ANSWER (-344, 43
4
), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-371, 48
1
), (154, 50) */
/* CIF PROCEDURECALL (-371, 48
4
), (154, 50) */
CALL writeln('All OK (1)');
/* CIF ANSWER (-181, 43
1
), (100, 35) */
/* CIF ANSWER (-181, 43
4
), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-213, 48
1
), (164, 50) */
/* CIF PROCEDURECALL (-213, 48
4
), (164, 50) */
CALL writeln('NOT OK (1)');
ENDDECISION;
/* CIF DECISION (-252, 54
6
), (100, 70) */
/* CIF DECISION (-252, 54
9
), (100, 70) */
DECISION 3 in seq;
/* CIF ANSWER (-338, 63
6
), (100, 35) */
/* CIF ANSWER (-338, 63
9
), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-370, 68
6
), (164, 50) */
/* CIF PROCEDURECALL (-370, 68
9
), (164, 50) */
CALL writeln('NOT OK (2)');
/* CIF ANSWER (-166, 63
6
), (100, 35) */
/* CIF ANSWER (-166, 63
9
), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-196, 68
6
), (161, 50) */
/* CIF PROCEDURECALL (-196, 68
9
), (161, 50) */
CALL writeln('All OK (2)');
ENDDECISION;
/* CIF NEXTSTATE (-252, 75
1
), (100, 50) */
/* CIF NEXTSTATE (-252, 75
4
), (100, 50) */
NEXTSTATE Wait;
...
...
@@ -122,29 +124,29 @@ ENDDECISION;
ENDSTATE;
/* CIF STATE (-252, 75
1
), (100, 50) */
/* CIF STATE (-252, 75
4
), (100, 50) */
STATE Wait;
/* CIF INPUT (-252, 82
1
), (100, 50) */
/* CIF INPUT (-252, 82
4
), (100, 50) */
INPUT go(msg);
/* CIF DECISION (-259, 88
6
), (114, 70) */
/* CIF DECISION (-259, 88
9
), (114, 70) */
DECISION msg = 'hello'
/* CIF COMMENT (-125, 89
6
), (128, 50) */
/* CIF COMMENT (-125, 89
9
), (128, 50) */
COMMENT 'Boolean test
on string value';
/* CIF ANSWER (-41, 97
6
), (100, 35) */
/* CIF ANSWER (-41, 97
9
), (100, 35) */
(FALSE):
/* CIF OUTPUT (-60, 102
6
), (139, 50) */
/* CIF OUTPUT (-60, 102
9
), (139, 50) */
OUTPUT rezult(first_msg);
/* CIF NEXTSTATE (-41, 109
1
), (100, 50) */
/* CIF NEXTSTATE (-41, 109
4
), (100, 50) */
NEXTSTATE Wait;
/* CIF ANSWER (-312, 97
6
), (100, 35) */
/* CIF ANSWER (-312, 97
9
), (100, 35) */
(TRUE):
/* CIF OUTPUT (-334, 102
6
), (145, 50) */
/* CIF OUTPUT (-334, 102
9
), (145, 50) */
OUTPUT rezult('Welcome')
/* CIF COMMENT (-170, 102
6
), (95, 50) */
/* CIF COMMENT (-170, 102
9
), (95, 50) */
COMMENT 'Send raw
string';
/* CIF NEXTSTATE (-312, 109
1
), (100, 50) */
/* CIF NEXTSTATE (-312, 109
4
), (100, 50) */
NEXTSTATE Running;
ENDDECISION;
ENDSTATE;
...
...
tests/regression/test2/orchestrator.pr
View file @
c2762c46
...
...
@@ -14,23 +14,45 @@ DCL major_cycle, sub_cycle T_UInt32;
/* CIF ENDTEXT */
/* CIF START (-209, 208), (100, 50) */
START;
/* CIF PROCEDURECALL (-25
4
, 273), (189, 50) */
/* CIF PROCEDURECALL (-25
3
, 273), (189, 50) */
CALL writeln
('[Orchestrator] Startup');
/* CIF TASK (-23
1
, 338), (143, 50) */
/* CIF TASK (-23
0
, 338), (143, 50) */
TASK intr := obt_pulse4;
/* CIF TASK (-231, 403), (144, 50) */
/* CIF OUTPUT (-224, 403), (130, 35) */
OUTPUT telemetry;
/* CIF TASK (-231, 453), (144, 50) */
TASK major_cycle := 1,
sub_cycle := 0;
/* CIF NEXTSTATE (-217,
46
8), (116, 50) */
/* CIF NEXTSTATE (-217,
51
8), (116, 50) */
NEXTSTATE Wait_for_GUI;
/* CIF STATE (-18, 53), (116, 50) */
STATE Wait_for_GUI;
/* CIF INPUT (-28, 123), (136, 50) */
INPUT start_simulation
(gnc_input);
/* CIF PROCEDURECALL (-55, 188), (190, 50) */
CALL writeln
('[Orchestrator] Running');
/* CIF NEXTSTATE (-10, 253), (100, 50) */
NEXTSTATE Running;
ENDSTATE;
/* CIF STATE (502, 32), (100, 50) */
STATE Running;
/* CIF INPUT (314, 102), (100, 50) */
/* CIF INPUT (757, 102), (136, 50) */
INPUT start_simulation
(gnc_input)
/* CIF COMMENT (913, 102), (169, 50) */
COMMENT 'Input from gui
stops the simulation';
/* CIF NEXTSTATE (767, 167), (116, 50) */
NEXTSTATE Wait_for_GUI;
/* CIF INPUT (311, 102), (105, 50) */
INPUT pulse
/* CIF COMMENT (43
4
, 102), (114, 50) */
/* CIF COMMENT (43
6
, 102), (114, 50) */
COMMENT 'Periodic call';
/* CIF PROCEDURECALL (175, 167), (377, 50) */
CALL S_SET_GNC_LV_SIM_CONTEXT_FOR_NEXT_MAJOR_CYCLE
...
...
@@ -63,8 +85,6 @@ sub_cycle = 0
/* CIF COMMENT (477, 459), (250, 50) */
COMMENT 'Plot only every 50 major cycles
(otherwise performance is too low)';
/* CIF ANSWER (449, 562), (100, 35) */
(false):
/* CIF ANSWER (254, 562), (100, 35) */
(true):
/* CIF TASK (169, 612), (270, 68) */
...
...
@@ -72,17 +92,15 @@ TASK plot_data!major_cycle := major_cycle,
plot_data!subcycle := sub_cycle,
plot_data!gnc_inputs := gnc_input,
plot_data!gnc_outputs := gnc_output;
/* CIF OUTPUT (2
38
, 695), (1
32
, 50) */
/* CIF OUTPUT (2
24
, 695), (1
59
, 50) */
OUTPUT plot(plot_data);
/* CIF ANSWER (449, 562), (100, 35) */
(false):
ENDDECISION;
/* CIF DECISION (305, 760), (118, 70) */
DECISION sub_cycle = 7
/* CIF COMMENT (443, 770), (199, 50) */
COMMENT 'Compute next major cycle';
/* CIF ANSWER (424, 850), (100, 35) */
(false):
/* CIF TASK (377, 900), (194, 50) */
TASK sub_cycle := sub_cycle + 1;
/* CIF ANSWER (197, 850), (100, 35) */
(true):
/* CIF TASK (137, 900), (220, 53) */
...
...
@@ -90,29 +108,13 @@ TASK sub_cycle := 0,
major_cycle := major_cycle + 1;
/* CIF PROCEDURECALL (127, 968), (240, 50) */
CALL S_JUMP_TO_NEXT_MAJOR_CYCLE;
/* CIF ANSWER (424, 850), (100, 35) */
(false):
/* CIF TASK (377, 900), (194, 50) */
TASK sub_cycle := sub_cycle + 1;
ENDDECISION;
/* CIF NEXTSTATE (314, 1033), (100, 50) */
NEXTSTATE Running;
/* CIF INPUT (757, 102), (136, 50) */
INPUT start_simulation
(gnc_input)
/* CIF COMMENT (913, 102), (169, 50) */
COMMENT 'Input from gui
stops the simulation';
/* CIF NEXTSTATE (767, 167), (116, 50) */
NEXTSTATE Wait_for_GUI;
ENDSTATE;
/* CIF STATE (-18, 53), (116, 50) */
STATE Wait_for_GUI;
/* CIF INPUT (-28, 123), (136, 50) */
INPUT start_simulation
(gnc_input);
/* CIF PROCEDURECALL (-55, 188), (190, 50) */
CALL writeln
('[Orchestrator] Running');
/* CIF NEXTSTATE (-10, 253), (100, 50) */
NEXTSTATE Running;
ENDSTATE;
ENDPROCESS orchestrator;
\ No newline at end of file
tests/regression/test8/orchestrator.pr
View file @
c2762c46
...
...
@@ -31,7 +31,9 @@ endfor;
TASK for x in foo(1,2):
call writeln(x);
endfor;
/* CIF NEXTSTATE (-569, 449), (91, 39) */
/* CIF TASK (-582, 449), (118, 35) */
TASK toto := (toto);
/* CIF NEXTSTATE (-569, 499), (91, 39) */
NEXTSTATE Stopped;
/* CIF STATE (-340, 38), (91, 35) */
STATE Stopped;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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