class STSParser
token TOP_INST TOP_INST_END DATA_START DATA_SCRIPT DATA_END PROC_START PROC_INST PROC_END TERMIN IDENT ASSIGN COLON NUMBER STRING P_EQ P_MULT P_PLUS P_MINUS P_HAT P_IN P_PERC P_TILDA P_COLON P_LPAR P_RPAR P_LSQBR P_RSQBR P_COMMA SEP_SLASH
rule
program : opt_termins blocks opt_termins {result = val}
blocks: blocks TERMIN block { val << val ; result = val}
| block { result = Array.new(1, val[0] )}
block: top_stmt { result = val }
| data_block { result = val[0] } | proc_block { result = val[0] }
top_stmt: TOP_INST top_options TOP_INST_END {result = GramNode.new
( :TOP_BLOCK, val, val ) }
data_block: DATA_START data_engine_option IDENT data_options TERMIN DATA_SCRIPT DATA_END { val ; result = GramNode.new
( :DATA_BLOCK, GramNode.new
(:ident, val), val, GramNode.new
( :string, val)) }
proc_block: PROC_START IDENT proc_options TERMIN proc_stmts TERMIN PROC_END { result = GramNode.new
( :PROC_BLOCK, GramNode.new
(:ident, val), val, val) }
top_options : { result = nil }
| value_or_kv { result = Array.new(1, val[0]) } | top_options value_or_kv { val[0] << val[1]; result = val[0]}
value_or_kv: opt_primary {result = val}
| kv {result = val[0]}
data_engine_option : { result = nil }
| COLON IDENT { result = val[1]}
data_options : {result = nil}
| options {result = val[0]}
proc_options : {result = nil}
| options {result = val[0]}
options: options key_or_kv { val << val; result = val}
| key_or_kv { result = Array.new(1, val[0]) }
key_or_kv: key {result = val }
| kv {result = val[0] }
key: IDENT { result = GramNode.new
(:option, val, true ) }
kv : IDENT ASSIGN opt_primary { result = GramNode.new
(:option, val, val) }
opt_primary : NUMBER { result = GramNode.new
(:num , val) }
| STRING { result = GramNode.new(:string, val[0]) } | IDENT { result = GramNode.new(:ident , val[0]) }
proc_stmts : proc_stmts TERMIN proc_stmt { val << val; result = val }
| proc_stmt { result = Array.new(1, val[0]) }
proc_stmt : PROC_INST optional_proc_stmt_options { result = GramNode.new
( :proc_stmt , GramNode.new
(:ident, val) , val) }
optional_proc_stmt_options : {result = nil }
| proc_stmt_options {result = val[0] }
proc_stmt_options : proc_stmt_options proc_primary { val << val ; result = val }
| proc_primary { result = Array.new(1, val[0] ) }
proc_primary : IDENT { result = GramNode.new
(:ident , val) }
| NUMBER { result = GramNode.new(:num , val[0]) } | STRING { result = GramNode.new(:string, val[0]) } | P_EQ { result = GramNode.new(:sign, val[0]) } | P_MULT { result = GramNode.new(:sign, val[0]) } | P_PLUS { result = GramNode.new(:sign, val[0]) } | P_MINUS { result = GramNode.new(:sign, val[0]) } | P_HAT { result = GramNode.new(:sign, val[0]) } | P_IN { result = GramNode.new(:sign, val[0]) } | P_PERC { result = GramNode.new(:sign, val[0]) } | P_TILDA { result = GramNode.new(:sign, val[0]) } | P_COLON { result = GramNode.new(:sign, val[0]) } | P_LPAR { result = GramNode.new(:sign, val[0]) } | P_RPAR { result = GramNode.new(:sign, val[0]) } | P_LSQBR { result = GramNode.new(:sign, val[0]) } | P_RSQBR { result = GramNode.new(:sign, val[0]) } | P_COMMA { result = GramNode.new(:sign, val[0]) } | SEP_SLASH { result = GramNode.new(:sign, val[0]) }
opt_termins : # empty
| termins
termins : termins TERMIN
| TERMIN
end
—- inner
def parse( tokens )
@tokens = tokens @yydebug = true do_parse()
end
def next_token
@tokens.shift
end
def on_error(t, val, vstack)
raise Racc::ParseError, sprintf( "Parse error on value %s (%s)\n", val.inspect, token_to_str(t) || '?' )
end
—- footer
require_relative(“sts_gram_node.rb”)
module STSParserDriver
def self.run( tokens ) parser = STSParser.new begin gram_tree = parser.parse( tokens ) rescue Racc::ParseError => e puts "Parser error detected" puts e.message runtime_error = RuntimeError.new( e.message ); runtime_error.set_backtrace( e.backtrace ); e.set_backtrace([]) raise runtime_error end end
end