include 'out-go.lm' global Out2: parser parser new_parser() { new P: parser() Input: _input = P->gets() Input->auto_trim( true ) return P } int rw_go_factor( Factor: indep::factor ) { if match Factor [`first_token_char] { send Out2 "data\[ts\]" } else if match Factor [tk_ident `[ expr `]] { send Out2 "[$Factor.tk_ident]\[ [rw_go_expr(Factor.expr)] \] } else if match Factor [tk_ident `( expr `)] { send Out2 "[$Factor.tk_ident]( [rw_go_expr(Factor.expr)] ) } elsif match Factor [`< type `> `( expr `)] { send Out2 "( [rw_go_type(Factor.type)] ) ( [rw_go_expr(Factor.expr)] ) } elsif match Factor [`( expr `)] { send Out2 "( [rw_go_expr(Factor.expr)] ) } elsif match Factor ['true'] { send Out2 'true' } elsif match Factor ['false'] { send Out2 'false' } elsif match Factor [`buffer] { send Out2 "string ( buffer\[:blen\] )" } else { send Out2 [$Factor] } } void rw_go_type( Type: indep::type ) { if match Type [`int] { send Out2 "int" } elsif match Type [`bool] { send Out2 "bool" } elsif match Type [`char] { send Out2 "byte" } elsif match Type [`ptr] { send Out2 "int" } elsif match Type [`byte] { send Out2 "unsigned char" } } void rw_go_abs_expr( Expr: indep::abs_expr ) { if ( Expr.Op ) { send Out2 "[rw_go_abs_expr(Expr.E1)] [$Expr.Op] [rw_go_abs_expr( Expr.E2 )]" } else { rw_go_factor( Expr.factor ) } } void rw_go_expr( Expr: indep::expr ) { AbsExpr: indep::abs_expr = indep::abs_comparative( Expr.comparative ) rw_go_abs_expr( AbsExpr ) } void rw_go_opt_array( OptArr: indep::opt_arr ) { if OptArr.expr { send Out2 "\[[rw_go_expr( OptArr.expr )]\]" } } int rw_go_var_decl( VarDecl: indep::var_decl ) { send Out2 "var [$VarDecl.tk_ident] [rw_go_opt_array(VarDecl.opt_arr)] [rw_go_type( VarDecl.type )] ; } void rw_go_opt_sub( OptSub: indep::opt_sub ) { if ( OptSub.expr ) send Out2 "\[[rw_go_expr(OptSub.expr)]\]" } int rw_go_expr_stmt( ExprStmt: indep::expr_stmt ) { if match ExprStmt [tk_ident opt_sub `= expr `;] { send Out2 "[$ExprStmt.tk_ident rw_go_opt_sub(ExprStmt.opt_sub)] = [rw_go_expr(ExprStmt.expr)]; } else if match ExprStmt [expr `;] { send Out2 "[rw_go_expr(ExprStmt.expr)]; } } int rw_go_if_stmt( IfStmt: indep::if_stmt ) { send Out2 "if ( [rw_go_expr( IfStmt.expr )] ) { " [rw_go_stmt_list( IfStmt._repeat_stmt )]" if ( IfStmt.opt_else._repeat_stmt ) { send Out2 "} else { " [rw_go_stmt_list( IfStmt.opt_else._repeat_stmt )]" } send Out2 "} } int rw_go_print_stmt( Stmt: indep::print_stmt ) { if match Stmt [`print_int expr `;] { send Out2 "fmt.Print( [rw_go_expr(Stmt.expr)] ); } else if match Stmt [`print_buf `;] { send Out2 "fmt.Print( string(buffer\[0:blen\]) ); } else if match Stmt [`print_str expr `;] { send Out2 "fmt.Print( [rw_go_expr( Stmt.expr )] ); } else if match Stmt [`print_token `;] { send Out2 "fmt.Print( data\[ts:te\] ); } else if match Stmt [`print_off `;] { send Out2 "fmt.Print( p ); } } int rw_go_ragel_stmt( Stmt: indep::ragel_stmt ) { send Out2 "[Stmt] } void rw_go_buf_stmt( BufStmt: indep::buf_stmt ) { switch BufStmt case [`buf_clear `( `) `;] { send Out2 " blen = 0; } case [`buf_append `( `) `;] { send Out2 " buffer\[blen\] = fc; " blen += 1; " buffer\[blen\] = 0; } } int rw_go_stmt( Stmt: indep::stmt ) { if match Stmt [var_decl] rw_go_var_decl( Stmt.var_decl ) else if match Stmt [expr_stmt] rw_go_expr_stmt( Stmt.expr_stmt ) else if match Stmt [if_stmt] rw_go_if_stmt( Stmt.if_stmt ) else if match Stmt [print_stmt] rw_go_print_stmt( Stmt.print_stmt ) else if match Stmt [buf_stmt] rw_go_buf_stmt( Stmt.buf_stmt ) else if match Stmt [ragel_stmt] rw_go_ragel_stmt( Stmt.ragel_stmt ) } void rw_go_stmt_list( StmtList: indep::stmt* ) { for Stmt: indep::stmt in repeat( StmtList ) rw_go_stmt( Stmt ) } int rw_go_action_block( ActionBlock: indep::action_block ) { Out2 = new_parser() if match ActionBlock [`{ stmt* `}] { send Out2 [ "{ rw_go_stmt_list( ActionBlock._repeat_stmt ) "} ] } else if match ActionBlock [`{ expr `}] { send Out2 "{ [rw_go_expr( ActionBlock.expr )] } } send Out2 [] eos } void rw_go( Output: stream ) { send Output "/* " * @LANG: go if ProhibitGenflags { send Output " * @PROHIBIT_GENFLAGS:[ProhibitGenflags] } send Output " * @GENERATED: true " */ " "package main "import \"fmt\" " Init: indep::stmt* = RagelTree.Init for Stmt: indep::stmt in Init { if match Stmt [Decl: var_decl] { Out2 = new_parser() rw_go_var_decl( Decl ) send Out2 [] eos send Output [$Out2->tree] } } Section: indep::section = RagelTree.section for Action: ragel::action_block in Section { # Reparse as lang-independent code. parse IndepActionBlock: indep::action_block[$Action] # Translate to specific language. rw_go_action_block( IndepActionBlock ) # Reparse back to ragel action block. Action = parse ragel::action_block[Out2->tree] } prints( Output, '\n', Section, '\n' ) send Output "var cs int; "var blen int; "var buffer \[1024\] byte; "var nfa_len int; "var nfa_count int; "var nfa_bp \[20\] struct { state int; p int; }; " "%% write data; " "func prepare() { for Stmt: indep::stmt in Init { if match Stmt [ExprStmt: expr_stmt] { Out2 = new_parser() rw_go_expr_stmt( ExprStmt ) send Out2 [] eos send Output [$Out2->tree] } } send Output " %% write init; "} " "func exec(data string) { " var p int = 0 " var pe int = len(data) if NeedsEof { send Output " var eof int = pe } send Output " %% write exec; "} "func finish() { " if cs >= [MachineName.mn_word]_first_final { " fmt.Println(\"ACCEPT\") " } else { " fmt.Println(\"FAIL\") " } "} send Output ~var inp []string = []string { for InputString: indep::input_string in RagelTree { send Output [^InputString ",\n"] } send Output "}; " send Output "func main() { " for _, data := range inp { " prepare() " exec(data) " finish() " } "} }