include 'ril.lm' namespace js_out token _IN_ /''/ token _EX_ /''/ lex token comment / '//' any* :> '\n' | '/*' any* :>> '*/' / token id /[a-zA-Z_][a-zA-Z_0-9]*/ token number / [0-9]+ / token symbol / '!' | '#' | '$' | '%' | '&' | '(' | ')' | '*' | '+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '[' | ']' | '^' | '|' | '~' / literal `{ `} token string / '"' ( [^"\\] | '\\' any ) * '"' | "'" ( [^'\\] | '\\' any ) * "'" / ignore /[ \t\v\r\n]+/ end def item [comment] | [id] | [number] | [symbol] | [string] | [`{ _IN_ item* _EX_ `} ] def js_out [_IN_ _EX_ item*] end namespace js_gen global Parser: parser void tok_list( TL: host::tok* ) { for Tok: host::tok in repeat(TL) { switch Tok case [host::`${ StmtList: stmt* host::`}$] { send Parser "{ " [stmt_list( StmtList )] "} } case [host::`={ Expr: expr host::`}=] { send Parser "([expr( Expr )])" } case [E: escape] { Str: str = $E send Parser "[Str.suffix( 1 )]" } default { send Parser [Tok] } } } void embedded_host( EmbeddedHost: embedded_host ) { switch EmbeddedHost case [`host `( string `, uint `) `={ TL: host::tok* host::`}=] { send Parser "([tok_list( TL )])" } case [`host `( string `, uint `) `${ TL: host::tok* host::`}$] { send Parser "{ " [tok_list( TL )] "} } case [`host `( string `, uint `) `@{ TL: host::tok* host::`}@] { send Parser [tok_list( TL )] } } void expr_factor( ExprFactor: expr_factor ) { switch ExprFactor case [EH: embedded_host] { send Parser [embedded_host( EH )] } case [O:`( TL: expr C: `)] { send Parser [O expr(TL) C] } case [ident O: `[ TL: expr C: `]] { send Parser [ExprFactor.ident O expr( TL ) C] } case ['offset' '(' Base: expr ',' Offset: expr ')'] { send Parser [expr( Offset )] } case ['deref' '(' Base: expr ',' Offset: expr ')'] { send Parser [Base] if $Base == 'data' send Parser ['.charCodeAt(' expr( Offset ) ')'] else send Parser ['[' expr( Offset ) ']'] } case [T: `TRUE] { T.data = 'true' send Parser [T] } case [F: `FALSE] { F.data = 'false' send Parser [F] } case [N: `nil] { N.data = '-1' send Parser [N] } case [Number: number] { number( Number ) } case [E1: embedded_host `-> E2: expr_factor] { embedded_host( E1 ) expr_factor( E2 ) } case [`cast Open: `( type Close: `) expr_factor] { expr_factor( ExprFactor._expr_factor ) } default { # Catches cases not specified send Parser [ExprFactor] } } void lvalue( ExprFactor: lvalue ) { switch ExprFactor case [EH: embedded_host] { send Parser [embedded_host( EH )] } case [ident O: `[ TL: expr C: `]] { send Parser [ExprFactor.ident O expr( TL ) C] } case [I: ident `[ E: expr `] `. F: ident] { send Parser "[I]\[[ expr( E )]\].[F] } case [E1: embedded_host `-> E2: lvalue] { # The accessor operator is contained wihtin the lhs. embedded_host( E1 ) lvalue( E2 ) } default { # Catches cases not specified send Parser [ExprFactor] } } void expr_factor_op( ExprFactorOp: expr_factor_op ) { switch ExprFactorOp case [B: `! expr_factor_op] { send Parser [B] expr_factor_op( ExprFactorOp._expr_factor_op ) } case [T: `~ expr_factor_op] { send Parser [T] expr_factor_op( ExprFactorOp._expr_factor_op ) } case [expr_factor] { expr_factor( ExprFactorOp.expr_factor ) } } void expr_bitwise( ExprBitwise: expr_bitwise ) { switch ExprBitwise case [expr_bitwise A: `& expr_factor_op] { expr_bitwise( ExprBitwise._expr_bitwise ) send Parser [A] expr_factor_op( ExprBitwise.expr_factor_op ) } case [expr_factor_op] { expr_factor_op( ExprBitwise.expr_factor_op ) } } void expr_mult( ExprMult: expr_mult ) { switch ExprMult case [expr_mult T: `* expr_bitwise] { expr_mult( ExprMult._expr_mult ) send Parser [T] expr_bitwise( ExprMult.expr_bitwise ) } case [expr_bitwise] { expr_bitwise( ExprMult.expr_bitwise ) } } void expr_add( ExprAdd: expr_add ) { switch ExprAdd case [expr_add Op: add_op expr_mult] { expr_add( ExprAdd._expr_add ) send Parser [Op] expr_mult( ExprAdd.expr_mult ) } case [expr_mult] { expr_mult( ExprAdd.expr_mult ) } } void expr_shift( ExprShift: expr_shift ) { switch ExprShift case [expr_shift Op: shift_op expr_add] { expr_shift( ExprShift._expr_shift ) send Parser [Op] expr_add( ExprShift.expr_add ) } case [expr_add] { expr_add( ExprShift.expr_add ) } } void expr_test_op( Op: test_op ) { switch Op case [ `== ] send Parser '===' case [ `!= ] send Parser '!==' default send Parser [Op] } void expr_test( ExprTest: expr_test ) { switch ExprTest case [expr_test test_op expr_shift] { expr_test( ExprTest._expr_test ) expr_test_op( ExprTest.test_op ) expr_shift( ExprTest.expr_shift ) } case [expr_shift] { expr_shift( ExprTest.expr_shift ) } } void expr( Expr: expr ) { expr_test( Expr.expr_test ) } void number( Number: number ) { switch Number case [`u `( uint `) ] send Parser [Number.uint] default send Parser [Number] } void type( Type: type ) { switch Type case 'u8' send Parser 'Uint8' case 'u16' send Parser 'Uint16' case 'u32' send Parser 'Uint32' case 's8' send Parser 'Int8' case 's16' send Parser 'Int16' case 's32' send Parser 'Int32' default send Parser 'Float64' } void num_list( NumList: num_list ) { number( NumList.number ) for CommaNum: comma_num in NumList { send Parser [', '] number( CommaNum.number ) } } void stmt( Stmt: stmt ) { switch Stmt case [EH: embedded_host] { send Parser [embedded_host( EH )] } case [A: static_array] { send Parser "var [A.ident] = new [type(A.type)]Array(\[ [num_list(A.num_list)]\]); } case [V: static_value] { send Parser "var [V.ident] = [V.number]; } case [ 'if' O: `( IfExpr: expr C: `) IfStmt: stmt ElseIfClauseList: else_if_clause* ElseClauseOpt: else_clause? ] { send Parser "if ( [expr(IfExpr)] ) " [stmt(IfStmt)] for ElseIfClause: else_if_clause in repeat( ElseIfClauseList ) { match ElseIfClause ['else if (' ElseIfExpr: expr ')' ElseIfStmt: stmt] send Parser "else if ( [expr(ElseIfExpr)] ) " [stmt(ElseIfStmt)] } if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) { send Parser "else " [stmt(ElseStmt)] } } case ['while' '(' WhileExpr: expr ')' WhileStmt: stmt] { send Parser "while ( [expr(WhileExpr)] ) " [stmt(WhileStmt)] } case ['switch' '(' SwitchExpr: expr ')' '{' StmtList: stmt* '}'] { send Parser "switch ( [expr(SwitchExpr)] ) { " [stmt_list(StmtList)] "} } case [ExprExpr: expr Semi: `;] { send Parser [expr(ExprExpr) Semi] } case [L: `{ TL: stmt* R: `}] { send Parser "{ " [stmt_list(TL)] "} } case [ TypeList: opt_const Type: type Ident: ident OptInit: opt_init Semi: `; ] { send Parser "var [Ident] if match OptInit [E: `= expr] { send Parser [E expr(OptInit.expr)] } send Parser [Semi] } case [Export: export_stmt] { send Parser "var [Export.ident] = [number(Export.number)]; } case ['fallthrough' ';'] { # Nothing needed here. } case [Index: index_stmt] { send Parser "var [Index.ident]" if match Index.opt_init [E: `= expr] { send Parser [E expr(Index.opt_init.expr)] } send Parser "; } case [case_block] { send Parser "case [expr( Stmt.case_block.expr )]: "[stmt_list( Stmt.case_block._repeat_stmt )] "break; } case [default_block] { send Parser "default: "[stmt_list( Stmt.default_block._repeat_stmt )] "break; } case [goto_label] { } case [G: goto_stmt] { } case [AS: assign_stmt] { send Parser "[lvalue(AS.LValue) AS.assign_op expr(AS.expr)]; } default { # catches unspecified cases send Parser [Stmt] } } void stmt_list( StmtList: stmt* ) { for Stmt: stmt in repeat( StmtList ) stmt( Stmt ) } void trans( Output: stream, Start: start ) { Parser = new parser() send Parser "'use strict'; if ( Start.opt_bom.bom ) send Output [Start.opt_bom.bom] stmt_list( Start._repeat_stmt ) CO: js_out::js_out = Parser->finish() if CO { send Output [CO] } else { send stderr "failed to parse output: [Parser->error] } } end void trans( Output: stream, Start: start ) { js_gen::trans( Output, Start ) } include 'rlhc-main.lm'