1 # Copyright (c) 2009 The Hewlett-Packard Development Company
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met: redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer;
8 # redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution;
11 # neither the name of the copyright holders nor the names of its
12 # contributors may be used to endorse or promote products derived from
13 # this software without specific prior written permission.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 # Authors: Nathan Binkert
29 from ply
import lex
, yacc
34 # C or C++ comment (ignore)
37 t
.lexer
.lineno
+= t
.value
.count('\n')
43 # Define a rule so we can track line numbers
46 t
.lexer
.lineno
+= len(t
.value
)
50 'machine' : 'MACHINE',
51 'in_port' : 'IN_PORT',
52 'out_port' : 'OUT_PORT',
54 'transition' : 'TRANS',
55 'structure' : 'STRUCT',
56 'external_type' : 'EXTERN_TYPE',
57 'enumeration' : 'ENUM',
59 'enqueue' : 'ENQUEUE',
60 'copy_head' : 'COPY_HEAD',
61 'check_allocate' : 'CHECK_ALLOCATE',
62 'check_stop_slots' : 'CHECK_STOP_SLOTS',
72 literals
= ':[]{}(),='
74 tokens
= [ 'EQ', 'NE', 'LT', 'GT', 'LE', 'GE',
75 'LEFTSHIFT', 'RIGHTSHIFT',
77 'PLUS', 'DASH', 'STAR', 'SLASH',
78 'DOUBLE_COLON', 'SEMICOLON',
79 'ASSIGN', 'DOT', 'LATENCY',
80 'IDENT', 'LIT_BOOL', 'FLOATNUMBER', 'NUMBER', 'STRING' ]
81 tokens
+= reserved
.values()
98 t_DOUBLE_COLON
= r
'::'
103 class TokenError(Exception):
104 def __init__(self
, msg
, t
):
105 super(TokenError
, self
).__init
__(msg
)
108 class ParseError(Exception):
109 def __init__(self
, msg
, t
):
110 super(ParseError
, self
).__init
__(msg
)
114 raise TokenError("Illegal character", t
)
117 r
'[a-zA-Z_][a-zA-Z_0-9]*'
118 if t
.value
== 'true':
123 if t
.value
== 'false':
128 if t
.value
.startswith('LATENCY_'):
132 t
.type = reserved
.get(t
.value
, 'IDENT') # Check for reserved words
135 def t_FLOATNUMBER(t
):
138 t
.value
= float(t
.value
)
140 raise TokenError("Illegal float", t
)
146 t
.value
= int(t
.value
)
148 raise TokenError("Illegal number", t
)
164 p
[0] = [ x
for x
in p
[1] if x
is not None ]
167 raise ParseError("Syntax error", t
)
178 """decls : decl decls
181 p
[0] = [ p
[1] ] + p
[2]
201 """latency : LATENCY"""
205 """latencies : latency latencies
210 """d_machine : MACHINE '(' ident pair_l ')' '{' decl_l '}'
211 | MACHINE '(' ident pair_l ')' ':' type_members '{' decl_l '}'
212 | MACHINE '(' ident pair_l ')' ':' latencies '{' decl_l '}'"""
218 decls
= [ x
for x
in decl_l
if x
is not None ]
219 p
[0] = Machine(p
[3], decls
)
222 "d_action : ACTION '(' ident pair_l ')' statement_l"
226 "d_in_port : IN_PORT '(' ident ',' type ',' var pair_l ')' statement_l"
230 "d_out_port : OUT_PORT '(' ident ',' type ',' var pair_l ')' SEMICOLON"
234 """t_trans : TRANS '(' ident_l ',' ident_l ',' ident pair_l ')' ident_l
235 | TRANS '(' ident_l ',' ident_l pair_l ')' ident_l"""
236 p
[0] = Transition("transition")
239 """d_extern : EXTERN_TYPE '(' type pair_l ')' SEMICOLON
240 | EXTERN_TYPE '(' type pair_l ')' '{' type_methods '}'"""
244 "d_global : GLOBAL '(' type pair_l ')' '{' type_members '}'"
248 "d_struct : STRUCT '(' type pair_l ')' '{' type_members '}'"
252 "d_enum : ENUM '(' type pair_l ')' '{' type_enums '}'"
256 "d_object : type ident pair_l SEMICOLON"
259 def p_d_func_decl(p
):
260 """d_func_decl : void ident '(' param_l ')' pair_l SEMICOLON
261 | type ident '(' param_l ')' pair_l SEMICOLON"""
265 """d_func_def : void ident '(' param_l ')' pair_l statement_l
266 | type ident '(' param_l ')' pair_l statement_l"""
267 p
[0] = Function(p
[2])
270 def p_type_members(p
):
271 """type_members : type_member type_members
275 def p_type_member(p
):
276 """type_member : type ident pair_l SEMICOLON
277 | type ident ASSIGN expr SEMICOLON"""
281 def p_type_methods(p
):
282 """type_methods : type_method type_methods
286 def p_type_method(p
):
287 "type_method : type_or_void ident '(' type_l ')' pair_l SEMICOLON"
292 """type_enums : type_enum type_enums
297 "type_enum : ident pair_l SEMICOLON"
307 """types : type ',' types
319 def p_type_or_void(p
):
320 """type_or_void : type
331 """params : param ',' params
345 """ident_l : '{' idents '}'
350 """idents : ident SEMICOLON idents
356 # Pair and pair lists
358 """pair_l : ',' pairs
366 """pairs : pair ',' pairs
375 """pair : ident '=' STRING
383 # Below are the rules for action descriptions
384 def p_statement_l(p
):
385 "statement_l : '{' statements '}'"
389 """statements : statement statements
394 """expr_l : expr ',' expr_l
400 """statement : expr SEMICOLON
401 | expr ASSIGN expr SEMICOLON
402 | ENQUEUE '(' var ',' type pair_l ')' statement_l
403 | PEEK '(' var ',' type ')' statement_l
404 | COPY_HEAD '(' var ',' var pair_l ')' SEMICOLON
405 | CHECK_ALLOCATE '(' var ')' SEMICOLON
406 | CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMICOLON
408 | RETURN expr SEMICOLON"""
411 def p_if_statement(p
):
412 """if_statement : IF '(' expr ')' statement_l ELSE statement_l
413 | IF '(' expr ')' statement_l
414 | IF '(' expr ')' statement_l ELSE if_statement"""
421 | ident '(' expr_l ')'
423 | THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_l ')'
424 | THIS DOT var '[' expr ']' DOT var DOT ident
425 | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' expr_l ')'
426 | CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident
428 | expr DOT ident '(' expr_l ')'
429 | type DOUBLE_COLON ident '(' expr_l ')'
430 | expr '[' expr_l ']'
444 | expr RIGHTSHIFT expr
445 | expr LEFTSHIFT expr
456 def p_enumeration(p
):
457 "enumeration : ident ':' ident"
465 yacc
.yacc(write_tables
=0)
467 slicc_generated_cc
= set([
468 'ControllerFactory.cc',
471 slicc_generated_hh
= set([
472 'ControllerFactory.hh',
475 'protocol_name.hh' ])
477 class Machine(object):
478 def __init__(self
, name
, decls
):
482 def add(self
, hh
, cc
):
483 hh
.add('%s_Controller.hh' % self
.name
)
484 hh
.add('%s_Profiler.hh' % self
.name
)
486 cc
.add('%s_Controller.cc' % self
.name
)
487 cc
.add('%s_Profiler.cc' % self
.name
)
488 cc
.add('%s_Transitions.cc' % self
.name
)
489 cc
.add('%s_Wakeup.cc' % self
.name
)
491 for decl
in self
.decls
:
492 decl
.add(hh
, cc
, self
.name
)
494 class Declaration(object):
497 def __init__(self
, name
):
500 def add(self
, hh
, cc
, name
=None):
501 #print '>>>', type(self).__name__, self.name
507 hh
.add('%s%s.hh' % (name
, self
.name
))
509 cc
.add('%s%s.cc' % (name
, self
.name
))
511 class Action(Declaration
): pass
512 class InPort(Declaration
): pass
513 class OutPort(Declaration
): pass
514 class Transition(Declaration
): pass
515 class Extern(Declaration
): pass
516 class Global(Declaration
):
519 class Struct(Declaration
):
522 class Enum(Declaration
):
525 class Object(Declaration
): pass
526 class Function(Declaration
):
529 def read_slicc(sources
):
530 if not isinstance(sources
, (list,tuple)):
531 sources
= [ sources
]
534 for source
in sources
:
535 for sm_file
in file(source
, "r"):
536 sm_file
= sm_file
.strip()
539 if sm_file
.startswith("#"):
541 sm_files
.append(sm_file
)
546 hh
= slicc_generated_hh
.copy()
547 cc
= slicc_generated_cc
.copy()
549 for filename
in filenames
:
552 results
= yacc
.parse(file(filename
, 'r').read())
553 except (TokenError
, ParseError
), e
:
554 sys
.exit("%s: %s:%d" % (e
, filename
, e
.token
.lineno
))
556 for result
in results
:
559 return list(hh
), list(cc
)
561 if __name__
== '__main__':
564 hh
, cc
= scan(read_slicc(sys
.argv
[1:]))