summaryrefslogtreecommitdiff
path: root/src/cgil
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2020-10-18 11:44:43 -0700
committerAdrian Thurston <thurston@colm.net>2020-10-18 11:44:43 -0700
commit85b76476de71f43d3eb25d6bef4ee6d84cb71f6c (patch)
tree65c127fbcf70e62d8a4848be2c9c4ff7d74d86a1 /src/cgil
parent86bb5882a70224a29650ccfa1e46c9b023c2a3ef (diff)
downloadcolm-85b76476de71f43d3eb25d6bef4ee6d84cb71f6c.tar.gz
lift all source code into src/ dirinto-src
Diffstat (limited to 'src/cgil')
-rw-r--r--src/cgil/.gitignore2
-rw-r--r--src/cgil/Makefile.am9
-rw-r--r--src/cgil/ragel.lm1027
-rw-r--r--src/cgil/ril.lm284
-rw-r--r--src/cgil/rlhc-c.lm462
-rw-r--r--src/cgil/rlhc-crack.lm536
-rw-r--r--src/cgil/rlhc-csharp.lm480
-rw-r--r--src/cgil/rlhc-d.lm511
-rw-r--r--src/cgil/rlhc-go.lm454
-rw-r--r--src/cgil/rlhc-java.lm504
-rw-r--r--src/cgil/rlhc-js.lm504
-rw-r--r--src/cgil/rlhc-julia.lm561
-rw-r--r--src/cgil/rlhc-main.lm19
-rw-r--r--src/cgil/rlhc-ocaml.lm609
-rw-r--r--src/cgil/rlhc-ruby.lm527
-rw-r--r--src/cgil/rlhc-rust.lm534
16 files changed, 7023 insertions, 0 deletions
diff --git a/src/cgil/.gitignore b/src/cgil/.gitignore
new file mode 100644
index 00000000..9ee64540
--- /dev/null
+++ b/src/cgil/.gitignore
@@ -0,0 +1,2 @@
+/Makefile.in
+/Makefile
diff --git a/src/cgil/Makefile.am b/src/cgil/Makefile.am
new file mode 100644
index 00000000..57d12e80
--- /dev/null
+++ b/src/cgil/Makefile.am
@@ -0,0 +1,9 @@
+
+data_DATA = $(CGIL_FILES)
+
+CGIL_FILES = ril.lm rlhc-main.lm \
+ rlhc-c.lm rlhc-csharp.lm rlhc-go.lm rlhc-js.lm rlhc-ruby.lm \
+ rlhc-crack.lm rlhc-d.lm rlhc-java.lm rlhc-julia.lm rlhc-ocaml.lm rlhc-rust.lm
+
+EXTRA_DIST = $(CGIL_FILES)
+
diff --git a/src/cgil/ragel.lm b/src/cgil/ragel.lm
new file mode 100644
index 00000000..1325bbb3
--- /dev/null
+++ b/src/cgil/ragel.lm
@@ -0,0 +1,1027 @@
+
+global GblActionParams: bool = false
+global GblMachineMap: map<str, machine> = new map<str, machine>()
+global GblCurMachine: machine
+global GblTargetMachine: str = ""
+global GblSearchMachine: str = ""
+global GblWantSection: bool = false
+global GblIncludeDepth: int = 0
+global GblImport: bool = false
+global GblFileName: str = ""
+global GblIncludePaths: list<str> = new list<str>()
+
+struct saved_globals
+ FileName: str
+ TargetMachine: str
+ SearchMachine: str
+ WantSection: bool
+ IncludeDepth: int
+ Import: bool
+end
+
+global GblSavedGlobals: list<saved_globals> = new list<saved_globals>()
+
+void saveGlobals()
+{
+ new SG: saved_globals()
+
+ SG->FileName = GblFileName
+ SG->TargetMachine = GblTargetMachine
+ SG->SearchMachine = GblSearchMachine
+ SG->WantSection = GblWantSection
+ SG->Import = GblImport
+ SG->IncludeDepth = GblIncludeDepth
+
+ GblSavedGlobals->push_tail( SG )
+}
+
+void restoreGlobals()
+{
+ SG: saved_globals = GblSavedGlobals->pop_tail()
+
+ GblFileName = SG->FileName
+ GblTargetMachine = SG->TargetMachine
+ GblSearchMachine = SG->SearchMachine
+ GblWantSection = SG->WantSection
+ GblImport = SG->Import
+ GblIncludeDepth = SG->IncludeDepth
+}
+
+struct include_history_item
+ FileName: str
+ SectionName: str
+end
+
+bool isDuplicateInclude( From: machine, FileName: str, SectionName: str )
+{
+ for Item: include_history_item in From->IncludeHistory {
+ if Item->FileName == FileName && Item->SectionName == SectionName {
+ return true
+ }
+ }
+ return false
+}
+
+void addIncludeItem( From: machine, FileName: str, SectionName: str )
+{
+ new Item: include_history_item()
+ Item->FileName = FileName
+ Item->SectionName = SectionName
+ From->IncludeHistory->push_tail( Item )
+}
+
+struct machine
+ Name: str
+ ActionParams: map<str, str>
+ IncludeHistory: list<include_history_item>
+end
+
+
+rl ident
+ /( alpha | '_' ) ( alpha | digit | '_' )*/
+
+rl number
+ / digit+ /
+
+rl hex_number
+ / '0x' [0-9a-fA-F]+ /
+
+rl hex_char
+ / '0x' [0-9a-fA-F]{2} /
+
+rl NL / '\n' /
+
+rl c_comment
+ / '/*' ( any | NL )* :>> '*/' /
+
+rl cpp_comment
+ / '//' [^\n]* NL /
+
+rl ruby_comment
+ / '#' [^\n]* NL /
+
+rl s_literal
+ / "'" ([^'\\\n] | '\\' (any | NL))* "'" /
+
+rl d_literal
+ / '"' ([^"\\] | NL | '\\' (any | NL))* '"' /
+
+rl host_re_literal
+ / '/' ([^/\\] | NL | '\\' (any | NL))* '/' /
+
+#
+# Consuming ragel defintions without parsing. Used for included sections we
+# don't want and for import (TODO).
+#
+namespace consume
+ lex
+ token h_word / [a-zA-Z_][a-zA-Z0-9_]* /
+
+ token h_open /'{'/
+ token h_close /'}'/
+
+ token h_number /digit+/
+ token h_hex_number /'0x' [0-9a-fA-F]+/
+
+ token h_comment
+ / c_comment | cpp_comment /
+
+ token h_string
+ / s_literal | d_literal /
+
+ token h_whitespace
+ / ( [ \t] | NL )+ /
+
+ token h_any / any /
+ end
+
+ def host_tok
+ [h_word]
+ | [h_number]
+ | [h_hex_number]
+ | [h_comment]
+ | [h_string]
+ | [h_whitespace]
+ | [h_open host_tok* h_close]
+ | [h_any]
+
+ lex
+ ignore /[\t\n ]+/
+ ignore /'#' any* :> '\n'/
+
+ literal `}%%
+
+ token word / [a-zA-Z_][a-zA-Z0-9_]* /
+ token uint / number /
+ token hex / hex_number /
+
+ token string /
+ '"' ( [^"\\] | '\\' any )* '"' 'i'? |
+ "'" ( [^'\\] | '\\' any )* "'" 'i'? |
+ "[" ( [^\]\\] | '\\' any )* "]" 'i'? #|
+ #"/" ( [^\/\\] | '\\' any )* "/" 'i'?
+ /
+
+
+ token open /'{'/ -ni
+ token close ni- /'}'/
+ token c_any / any /
+ end
+
+
+ # Garbling up a machine, no interpretation
+ def tok
+ [word]
+ | [uint]
+ | [hex]
+ | [string]
+ | [open host_tok* h_close]
+ | [c_any]
+end
+
+# State reference.
+namespace state_ref
+ lex
+ ignore /[\t\n ]+/
+ literal `:: `; `)
+ token word /[a-zA-Z_][a-zA-Z0-9_]*/
+ end
+
+ def state_ref
+ [opt_name_sep state_ref_names] :Ref
+
+ def opt_name_sep
+ [`::] :ColonColon
+ | [] :Empty
+
+ # List of names separated by ::
+ def state_ref_names
+ [state_ref_names `:: word] :Rec
+ | [word] :Base
+end
+
+namespace inline
+
+ def inline_expr
+ [expr_item_list] :List
+
+ def expr_item_list
+ [expr_item_list expr_item] :Rec
+ | [] :Empty
+
+ def expr_item
+ [expr_any] :ExprAny
+ | [expr_symbol] :ExprSymbol
+ | [expr_interpret] :ExprInterpret
+
+ def expr_any
+ [whitespace] :WS
+ | [comment] :Comment
+ | [string] :String
+ | [number] :Number
+ | [hex_number] :Hex
+ | [ident] :Ident
+ | [c_any] :Any
+
+ def expr_symbol
+ [`,] :Comma | [`(] :Open | [`)] :Close | [`*] :Star | [`::] :DoubleColon
+
+ def expr_interpret
+ [`fpc] :Fpc
+ | [`fc] :Fc
+ | [`fcurs] :Fcurs
+ | [`ftargs] :Ftargs
+ | [`fentry `( state_ref::state_ref state_ref::`)] :Fentry
+ | [var_ref] :VarRef
+
+ def inline_block
+ [block_item_list] :List
+
+ def block_item_list
+ [block_item block_item_list] :Rec
+ | [] :Base
+
+ def block_item
+ [expr_any] :ExprAny
+ | [block_symbol] :BlockSymbol
+ | [block_interpret] :BlockInterpret
+ | [`{ inline_block `}] :RecBlock
+
+ def block_symbol
+ [`,] :B1 | [`;] :B2 | [`(] :B3 | [`)] :B4 | [`*] :B5 | [`::] :B6
+
+ def block_interpret
+ [expr_interpret] :ExprInterpret
+ | [`fhold whitespace? `;] :Fhold
+ | [`fgoto whitespace? `* inline_expr `;] :FgotoExpr
+ | [`fnext whitespace? `* inline_expr `;] :FnextExpr
+ | [`fcall whitespace? `* inline_expr `;] :FcallExpr
+ | [`fncall whitespace? `* inline_expr `;] :FncallExpr
+ | [`fexec inline_expr `;] :Fexec
+ | [`fgoto state_ref::state_ref state_ref::`;] :FgotoSr
+ | [`fnext state_ref::state_ref state_ref::`;] :FnextSr
+ | [`fcall state_ref::state_ref state_ref::`;] :FcallSr
+ | [`fncall state_ref::state_ref state_ref::`;] :FncallSr
+ | [`fret `;] :Fret
+ | [`fnret `;] :Fnret
+ | [`fbreak `;] :Fbreak
+ | [`fnbreak `;] :Fnbreak
+end
+
+namespace ragel
+ lex
+ literal `}%% -ni
+
+ ignore /[\t\n ]+/
+ ignore /'#' any* :> '\n'/
+
+ literal `^ `| `- `, `: `! `? `.
+ literal `( `) `{ -ni ni- `} `* `& `+
+
+ literal `-- `:> `:>> `<: `-> `**
+
+ literal `|* `*| `=>
+
+ literal `@ `> `< `% `$
+ literal `from `to `eof `lerr `err
+ literal `when `inwhen `outwhen `>? `$? `%?
+
+ literal `:= `|= `= `; `.. `../i `::
+
+ literal `>~ `$~ `%~ `<~ `@~ `<>~
+ literal `>* `$* `%* `<* `@* `<>*
+ literal `>/ `$/ `%/ `</ `@/ `<>/
+ literal `>! `$! `%! `<! `@! `<>!
+ literal `>^ `$^ `%^ `<^ `@^ `<>^
+ literal `<>
+
+ literal `%%--{ -ni `%%++{ -ni
+
+ token include_tok
+ /'include'/
+ {
+ # Take off the include token.
+ input->pull( match_length )
+
+ # Parse the include details, up to the the ';' and stop there.
+ parse_stop Spec: include_spec(input)[]
+
+ Fn: str
+ Machine: str
+ if Spec.string
+ Fn = $Spec.string
+ if Spec.word
+ Machine = $Spec.word
+
+ Stream: stream = ragelInclude( Fn, Machine )
+
+ if Stream {
+ input->push( "}--%%" )
+ input->push_stream( Stream )
+ input->push( "%%--{" )
+ }
+ }
+
+ token import_tok
+ /'import'/
+ {
+ # Take off the include token.
+ input->pull( match_length )
+
+ # Parse the import details, up to the the ';' and stop there.
+ parse_stop Spec: import_spec(input)[]
+
+ Fn: str
+ if Spec.string
+ Fn = $Spec.string
+
+ Stream: stream = ragelImport( Fn )
+
+ if Stream {
+ input->push( "}++%%" )
+ input->push_stream( Stream )
+ input->push( "%%++{" )
+ }
+ }
+
+
+ literal `machine `action `variable `alphtype
+ `access `write `getkey `export `prepush
+ `postpop `nfaprepush `nfapostpop
+
+ literal `:nfa `:nfa_greedy `:nfa_lazy `:nfa_wrap
+ `:nfa_wrap_greedy `:nfa_wrap_lazy
+ `:cond `:condplus `:condstar `):
+
+ token string /
+ '"' ( [^"\\] | '\\' any )* '"' 'i'? |
+ "'" ( [^'\\] | '\\' any )* "'" 'i'?
+ /
+
+ token lex_regex_open /'/'/ -ni
+ token lex_sqopen_pos /'['/ -ni
+ token lex_sqopen_neg /'[^'/ -ni
+
+ token word / [a-zA-Z_][a-zA-Z0-9_]* /
+ token uint / number /
+ token hex / hex_number /
+ end
+
+ def include_spec
+ [word `;]
+ | [string `;]
+ | [word string `;]
+
+ def import_spec
+ [string `;]
+
+ lex
+ token re_dot / '.' /
+ token re_star / '*' /
+ token re_char / ^( '\\' | '.' | '*' | '[' | '/' ) | '\\' . any /
+ token re_close / '/' 'i'? /
+ token re_sqopen_pos /'['/
+ token re_sqopen_neg /'[^'/
+ end
+
+ lex
+ token re_or_dash / '-' /
+ token re_or_char / ^( '\\' | '-' | ']' ) | '\\' . any /
+ token re_or_sqclose / ']' /
+ end
+
+ # Not cannot start with '{', terminated by ';', rewritten into { inline_expr }
+ token _inline_expr_reparse
+ /[^{;] [^;]* ';'/ {
+ R: str = input->pull( match_length - 1 )
+ input->pull( 1 )
+ input->push( "}" )
+ input->push( R )
+ input->push( "{" )
+ }
+
+ token variable_name /ident/
+
+ # This region is for deciding if we want to parse a ragel section, or if we
+ # want to consume it without interpreting. Consuming is for included
+ # sections we don't want and all sections in an imported file.
+ lex
+ token ign_select /''/
+ {
+ if GblWantSection
+ input->push( make_token( typeid<ign_want>, '' ) )
+ else
+ input->push( make_token( typeid<ign_ignore>, '' ) )
+ }
+
+ token ign_want //
+ token ign_ignore //
+ end
+
+ #
+ # Machine name word. We inspect it to determine if we are interested in the
+ # section.
+ #
+ lex
+ token mn_word / [a-zA-Z_][a-zA-Z0-9_]* /
+ {
+ S: str = input->pull(match_length)
+ IgnWord: mn_word = make_token( typeid<mn_word>, S )
+ input->push( IgnWord )
+
+ if ( GblImport )
+ GblWantSection = false
+ else if ( GblSearchMachine != "" ) {
+ if ( S != GblSearchMachine )
+ GblWantSection = false
+ else
+ GblWantSection = true
+ }
+ else {
+ GblWantSection = true
+ }
+
+ Name: str = S #$lhs.mn_word
+ if GblTargetMachine != ""
+ Name = GblTargetMachine
+
+ Machine: machine = GblMachineMap->find( Name )
+
+ if !Machine
+ {
+ Machine = new machine()
+ Machine->Name = Name
+ Machine->ActionParams = new map<str, str>()
+ Machine->IncludeHistory = new list<include_history_item>()
+ GblMachineMap->insert( Machine->Name, Machine )
+ }
+
+ GblCurMachine = Machine
+
+ # print "want section: [GblWantSection]
+ }
+ end
+
+
+ def inline_expr_reparse
+ [_inline_expr_reparse] :Reparse
+ | [action_expr] :ActionExpr
+
+ def join
+ [join `, expression] :Rec
+ | [expression] :Base
+
+ def expression
+ [expr_left expression_op_list] :Expression
+
+ def expression_op_list
+ [expression_op expression_op_list] :Op
+ | [] :Empty
+
+ def expression_op
+ [`| term] :Or
+ | [`& term] :And
+ | [`- term] :Sub
+ | [`-- term] :Ssub
+
+ def expr_left
+ [term] :Term
+
+ def term
+ [term_left term_op_list_short] :Term
+
+ def term_left
+ [factor_label] :FactorLabel
+
+ # This list is done manually to get shortest match.
+ def term_op_list_short
+ [] :Empty
+ | [term_op term_op_list_short] :Terms
+
+ def term_op
+ [factor_label] :None
+ | [`. factor_label] :Dot
+ | [`:> factor_label] :ColonLt
+ | [`:>> factor_label] :ColonLtLt
+ | [`<: factor_label] :GtColon
+
+ def factor_label
+ [word `: factor_label] :Label
+ | [factor_ep] :Ep
+
+ def factor_ep
+ [factor_aug `-> epsilon_target] :Epsilon
+ | [factor_aug] :Base
+
+ def epsilon_target
+ [epsilon_target `:: word] :Rec
+ | [word] :Base
+
+ def action_expr
+ [`{ CInlineExpr: inline::inline_expr inline::`}] :ActionExpr
+
+ def action_block
+ [`{ CInlineBlock: inline::inline_block inline::`}] :ActionBlock
+
+ def action_arg_list
+ [action_arg_list `, action_ref] :Rec
+ | [action_ref] :Base
+
+ def opt_action_arg_list
+ [action_arg_list] :List
+ | [] :Empty
+
+ def named_action_ref
+ [word] :Plain
+ {
+ if ( GblCurMachine->ActionParams->find( $lhs.word ) )
+ reject
+ }
+ | [word `( opt_action_arg_list `)] :Args
+ {
+ if ( ! GblCurMachine->ActionParams->find( $lhs.word ) )
+ reject
+ }
+
+ def action_ref
+ [named_action_ref] :NamedRef
+ | [`( named_action_ref `)] :ParenNamed
+ | [action_block] :Block
+
+ def priority_name
+ [word] :Word
+
+ def error_name
+ [word] :Word
+
+ def priority_aug
+ [uint] :NoSign
+ | [`+ uint] :Plus
+ | [`- uint] :Minus
+
+ def aug_base
+ [`@] :Finish | [`>] :Enter | [`%] :Leave | [`$] :All
+
+ def aug_cond
+ [`>?] :Start1 | [`$?] :All1 | [`%?] :Leave1
+ | [`> `when] :Start2 | [`$ `when] :All2 | [`% `when] :Leave2
+ | [`inwhen] :Start3 | [`when] :All3 | [`outwhen] :Leave3
+
+ def aug_to_state
+ [`>~] :Start1 | [`<~] :NotStart1 | [`$~] :All1
+ | [`%~] :Final1 | [`@~] :NotFinal1 | [`<>~] :Middle1
+ | [`> `to] :Start2 | [`< `to] :NotStart2 | [`$ `to] :All2
+ | [`% `to] :Final2 | [`@ `to] :NotFinal2 | [`<> `to] :Middle2
+
+ def aug_from_state
+ [`>*] :Start1 | [`<*] :NotStart1 | [`$*] :All1
+ | [`%*] :Final1 | [`@*] :NotFinal1 | [`<>*] :Middle1
+ | [`> `from] :Start2 | [`< `from] :NotStart2 | [`$ `from] :All2
+ | [`% `from] :Final2 | [`@ `from] :NotFinal2 | [`<> `from] :Middle2
+
+ def aug_eof
+ [`>/] :Start1 | [`</] :NotStart1 | [`$/] :All1
+ | [`%/] :Final1 | [`@/] :NotFinal1 | [`<>/] :Middle1
+ | [`> `eof] :Start2 | [`< `eof] :NotStart2 | [`$ `eof] :All2
+ | [`% `eof] :Final2 | [`@ `eof] :NotFinal2 | [`<> `eof] :Middle2
+
+ def aug_gbl_error
+ [`>!] :Start1 | [`<!] :NotStart1 | [`$!] :All1
+ | [`%!] :Final1 | [`@!] :NotFinal1 | [`<>!] :Middle1
+ | [`> `err] :Start2 | [`< `err] :NotStart2 | [`$ `err] :All2
+ | [`% `err] :Final2 | [`@ `err] :NotFinal2 | [`<> `err] :Middle2
+
+ def aug_local_error
+ [`>^] :Start1 | [`<^] :NotStart1 | [`$^] :All1
+ | [`%^] :Final1 | [`@^] :NotFinal1 | [`<>^] :Middle1
+ | [`> `lerr] :Start2 | [`< `lerr] :NotStart2 | [`$ `lerr] :All2
+ | [`% `lerr] :Final2 | [`@ `lerr] :NotFinal2 | [`<> `lerr] :Middle2
+
+ def factor_aug
+ [factor_aug aug_base action_ref] :ActionRef
+ | [factor_aug aug_base priority_aug] :PriorEmbed
+ | [factor_aug aug_base `( priority_name `, priority_aug `)] :NamedPriorEmbed
+ | [factor_aug aug_cond action_ref] :CondEmbed
+ | [factor_aug aug_cond `! action_ref] :NegCondEmbed
+ | [factor_aug aug_to_state action_ref] :ToStateAction
+ | [factor_aug aug_from_state action_ref] :FromStateAction
+ | [factor_aug aug_eof action_ref] :EofAction
+ | [factor_aug aug_gbl_error action_ref] :GblErrorAction
+ | [factor_aug aug_local_error action_ref] :LocalErrorDef
+ | [factor_aug aug_local_error `( error_name `, action_ref `)] :LocalErrorName
+ | [factor_rep] :Base
+
+ def factor_rep
+ [factor_neg factor_rep_op_list] :Op
+
+ def factor_rep_op_list
+ [factor_rep_op factor_rep_op_list] :Rec
+ | [] :Base
+
+ def factor_rep_op
+ [`*] :Star
+ | [`**] :StarStar
+ | [`?] :Optional
+ | [`+] :Plus
+ | [`{ factor_rep_num `}] :ExactRep
+ | [`{ `, factor_rep_num `}] :MaxRep
+ | [`{ factor_rep_num `, `}] :MinRep
+ | [`{ LowRep: factor_rep_num `, HighRep: factor_rep_num `}] :RangeRep
+
+ def factor_rep_num
+ [uint] :RepNum
+
+ def factor_neg
+ [`! factor_neg] :Bang
+ | [`^ factor_neg] :Caret
+ | [factor] :Base
+
+ def opt_max_arg
+ [`, action_ref] :Action
+ | [] :Empty
+
+ def nfastar
+ [`:nfa] :Default
+ | [`:nfa_lazy] :Lazy
+ | [`:nfa_greedy] :Greedy
+
+ def nfawrap
+ [`:nfa_wrap] :Default
+ | [`:nfa_wrap_lazy] :Lazy
+ | [`:nfa_wrap_greedy] :Greedy
+
+ def colon_cond
+ [`:cond] :Cond
+ | [`:condstar] :CondStar
+ | [`:condplus] :CondPlus
+
+ def factor
+ [alphabet_num] :AlphabetNum
+ | [word] :Word
+ | [string] :String
+ | [lex_sqopen_pos reg_or_data re_or_sqclose] :PosOrBlock
+ | [lex_sqopen_neg reg_or_data re_or_sqclose] :NegOrBlock
+ | [lex_regex_open regex re_close] :Regex
+ | [RL1: range_lit `.. RL2: range_lit] :Range
+ | [RL1: range_lit `../i RL2: range_lit] :RangeIndep
+ | [nfastar `( expression `,
+ Push: action_ref `, Pop: action_ref `, Init: action_ref `, Stay: action_ref `,
+ Repeat: action_ref `, Exit: action_ref `):] :Nfa
+ | [nfawrap `( expression `,
+ Push: action_ref `, Pop: action_ref `, Init: action_ref `, Stay: action_ref `,
+ Exit: action_ref `):] :NfaWrap
+ | [colon_cond `( expression `,
+ Init: action_ref `, Inc: action_ref `, Min: action_ref OptMax: opt_max_arg `):] :Cond
+ | [`( join `)] :Join
+
+ def regex
+ [reg_item_rep_list] :List
+
+ def reg_item_rep_list
+ [reg_item_rep_list reg_item_rep] :Rec
+ | [] :Base
+
+ def reg_item_rep
+ [reg_item re_star] :Star
+ | [reg_item] :Base
+
+ def reg_item
+ [re_sqopen_pos reg_or_data re_or_sqclose] :PosOrBlock
+ | [re_sqopen_neg reg_or_data re_or_sqclose] :NegOrBlock
+ | [re_dot] :Dot
+ | [re_char] :Char
+
+ def reg_or_data
+ [reg_or_data reg_or_char] :Data
+ | [] :Base
+
+ def reg_or_char
+ [re_or_char] :Char
+ | [Low: re_or_char re_or_dash High: re_or_char] :Range
+
+ def range_lit
+ [string] :String
+ | [alphabet_num] :AN
+
+ def alphabet_num
+ [uint] :Uint
+ | [`- uint] :Neg
+ | [hex] :Hex
+
+ def lm_act
+ [`=> action_ref] :ActionRef
+ | [action_block] :ActionBlock
+
+ def opt_lm_act
+ [lm_act] :Act
+ | [] :Empty
+
+ def lm_stmt
+ [join opt_lm_act `;] :LmStmt commit
+ | [assignment] :Assignment
+ | [action_spec] :ActionSpec
+
+ def lm_stmt_list
+ [lm_stmt_list lm_stmt] :Rec
+ | [lm_stmt] :Base
+
+ def lm
+ [join] :Join
+ | [`|* lm_stmt_list `*|] :Lm
+ | [`:nfa `|* lm_stmt_list `*|] :LmNfa
+
+ #
+ # Actions
+ #
+ def action_param
+ [word] :Word
+
+ def action_param_list
+ [action_param_list `, action_param] :Rec
+ | [action_param] :Base
+
+ def opt_action_param_list
+ [action_param_list] :List
+ | [] :Empty
+
+ def action_params
+ [`( opt_action_param_list `)] :List
+ {
+ GblActionParams = true
+ }
+
+ def action_spec
+ [`action word action_params action_block] :ActionSpecParams commit
+ {
+ # Track that this action has params so we can parse appropriately
+ # when reducing.
+ GblCurMachine->ActionParams->insert( $lhs.word, $lhs.word )
+
+ # Reset after parsing the block.
+ GblActionParams = false
+ }
+ | [`action word action_block] :ActionSpec commit
+ {
+ GblActionParams = false
+ }
+
+ def def_name
+ [word] :Word
+
+ #
+ # Machine Instantiations.
+ #
+ def assignment
+ [opt_export def_name `= join `;] :Assignment commit
+
+ def instantiation
+ [opt_export def_name `:= lm `;] :Instantiation commit
+
+ def nfa_expr
+ [nfa_expr `| term] :Union
+ | [term] :Base
+
+ def nfa_round_spec
+ [Depth: uint `, Group: uint] :Spec
+
+ def nfa_round_list
+ [nfa_round_list `, nfa_round_spec] :Recurse
+ | [nfa_round_spec] :Base
+
+ def nfa_rounds
+ [`( nfa_round_list `)] :Rounds
+
+ def nfa_union
+ [def_name `|= nfa_rounds nfa_expr `;] :NfaUnion commit
+
+ def alphtype_type
+ [W1: word] :One
+ | [W1: word W2: word] :Two
+
+ def opt_export
+ [`export] :Export
+ | [] :Base
+
+ def write_arg
+ [word] :Word
+
+ def machine_name
+ [`machine mn_word `;] :MachineName
+
+ def open_inc
+ [`%%--{] :OpenInc
+
+ def close_inc
+ [host::close_inc] :CloseInc
+
+ def include_statement
+ [open_inc host::section* close_inc] :IncPost commit
+
+ def open_imp
+ [`%%++{] :OpenImp
+
+ def close_imp
+ [host::close_imp] :CloseImp
+
+ def import_statement
+ [open_imp host::section* close_imp] :ImpPost commit
+
+ def statement
+ [assignment] :Assignment
+ | [instantiation] :Instantiation
+ | [nfa_union] :NfaUnion
+ | [action_spec] :ActionSpec
+ | [`prepush action_block] :PrePush commit
+ | [`postpop action_block] :PostPop commit
+ | [`variable variable_name inline_expr_reparse] :Variable commit
+ | [`alphtype alphtype_type `;] :AlphType commit
+ | [`access inline_expr_reparse] :Access commit
+ | [`write Cmd: word ArgList: write_arg* `;] :Write commit
+ | [`getkey inline_expr_reparse] :GetKey commit
+ | [import_statement] :Import commit
+ | [include_statement] :Include commit
+ | [`nfaprepush action_block] :NfaPrePush commit
+ | [`nfapostpop action_block] :NfaPostPop commit
+
+ def opt_machine_name
+ [machine_name] :MachineName
+ | [] :Empty
+
+ def ragel_start
+ [opt_machine_name ign_want statement*]
+ | [opt_machine_name ign_ignore consume::tok*]
+end
+
+str prepareLitString( Str: str )
+{
+ # TODO: escape sequences
+ return suffix( prefix( Str, Str.length - 1 ), 1 )
+}
+
+bool isAbsolutePath( Path: str )
+{
+ # TODO: implement this
+ return false
+}
+
+namespace path
+ lex
+ token slash /'/'/
+ token chars /[^\/]+/
+ end
+
+ def path
+ [Abs: slash? DirList: dir* File: chars]
+
+ def dir
+ [chars slash]
+
+ dir *concat_dir( Dir1: dir*, Dir2: dir* )
+ {
+ for D: dir* in Dir1 {
+ if match D [] {
+ D = Dir2
+ break
+ }
+ }
+ return Dir1
+ }
+end
+
+namespace host
+ token bom / 0xEF 0xBB 0xBF /
+
+ def opt_bom
+ [bom] :Bom
+ | []
+
+ def section
+ [`%%{ ragel::opt_machine_name ragel::ign_want ragel::statement* ragel::`}%%] :MultiLine
+ | [`%%{ ragel::opt_machine_name ragel::ign_ignore consume::tok* consume::`}%%] :Consume
+ | [tok] :Token
+end
+
+def start
+ [host::opt_bom SectionList: host::section*]
+
+list<str> makeIncludePathChecks( CurFileName: str, IncFileName: str )
+{
+ new L: list<str>()
+
+ parse CurPath: path::path[ CurFileName ]
+ parse IncPath: path::path[ IncFileName ]
+
+ if match IncPath.Abs [slash] {
+ # Included file is absolute
+ L->push_tail( IncFileName )
+ }
+ else {
+ # First add the location of current file
+ if match CurPath.DirList []
+ L->push_tail( IncFileName )
+ else {
+ # Current file path + Include Path + Include File
+ cons NewPath: path::path [
+ CurPath.Abs
+ path::concat_dir( CurPath.DirList, IncPath.DirList )
+ IncPath.File
+ ]
+
+ L->push_tail( $NewPath )
+ }
+
+ # Next add include file locations.
+ for Path: str in GblIncludePaths {
+ parse IncPath: path::path[ CurFileName ]
+ L->push_tail( "[Path]/[IncFileName]" )
+ }
+ }
+ return L
+}
+
+stream ragelInclude( IncFileName: str, Machine: str )
+{
+ if IncFileName
+ IncFileName = prepareLitString( IncFileName )
+
+ Checks: list<str>
+ if IncFileName
+ Checks = makeIncludePathChecks( GblFileName, IncFileName )
+ else {
+ Checks = new list<str>()
+ Checks->push_tail( GblFileName )
+
+ }
+
+ Stream: stream
+ OpenedName: str
+ for P: str in Checks {
+ Stream = open( P, "r" )
+ if Stream {
+ OpenedName = P
+ break
+ }
+ }
+
+ if !Stream {
+ print "error: could not open [IncFileName]
+ return nil
+ }
+
+ # Default to the current machine if none is specified.
+ if !Machine
+ Machine = GblCurMachine->Name
+
+ if isDuplicateInclude( GblCurMachine, IncFileName, Machine )
+ return nil
+
+ addIncludeItem( GblCurMachine, IncFileName, Machine )
+
+ saveGlobals()
+
+ GblIncludeDepth = GblIncludeDepth + 1
+ GblFileName = OpenedName
+
+ # Set up the search and target machine names. Search is the machine we want
+ # to include and target is the machine we include to.
+ GblSearchMachine = Machine
+ GblTargetMachine = GblCurMachine->Name
+
+ return Stream
+}
+
+stream ragelImport( IncFileName: str )
+{
+ if IncFileName
+ IncFileName = prepareLitString( IncFileName )
+
+ Checks: list<str>
+ if IncFileName
+ Checks = makeIncludePathChecks( GblFileName, IncFileName )
+ else {
+ Checks = new list<str>()
+ Checks->push_tail( GblFileName )
+ }
+
+ Stream: stream
+ OpenedName: str
+ for P: str in Checks {
+ Stream = open( P, "r" )
+ if Stream {
+ OpenedName = P
+ break
+ }
+ }
+
+ if !Stream {
+ print "error: could not open [IncFileName]
+ return nil
+ }
+
+ saveGlobals()
+
+ GblFileName = OpenedName
+ GblImport = true
+
+ return Stream
+}
diff --git a/src/cgil/ril.lm b/src/cgil/ril.lm
new file mode 100644
index 00000000..cde6ce93
--- /dev/null
+++ b/src/cgil/ril.lm
@@ -0,0 +1,284 @@
+namespace host
+ lex
+ rl NL / '\n' /
+
+ token escape
+ / '@' any /
+
+ literal `={ `}= `${ `}$ `@{ `}@
+
+ token host_any / any /
+ end
+
+ def tok
+ [`${ StmtList: stmt* `}$] :Stmt
+ | [`={ Expr: expr `}=] :Expr
+ | [escape] :Escape
+ | [host_any] :Any
+end
+
+lex
+ rl NL / '\n' /
+
+ rl s_literal
+ / "'" ([^'\\\n] | '\\' (any | NL))* "'" /
+
+ rl d_literal
+ / '"' ([^"\\] | NL | '\\' (any | NL))* '"' /
+
+ rl c_comment
+ / '/*' ( any | NL )* :>> '*/' /
+
+ rl cpp_comment
+ / '//' [^\n]* NL /
+
+ literal `array `value `TRUE `FALSE
+ `while `switch `case
+ `if `else `offset `index
+ `goto `deref `entry `label `default
+ `host `cast `match `pat
+
+ literal `uint `const
+ `s8 `s16 `s32 `s64
+ `s128 `nil `export
+ `fallthrough `u `c `break `continue
+
+ token ident
+ /( alpha | '_' ) ( alpha | digit | '_' )*/
+
+ token uint
+ / digit+ /
+
+ token hex_number
+ / '0x' [0-9a-fA-F]+ /
+
+ ignore
+ / c_comment | cpp_comment /
+
+ token string
+ / s_literal | d_literal /
+
+ ignore / ( [ \t] | NL )+ /
+
+ literal `$ `{ `} `= `[ `]
+ `- `, `. `; `( `) `:
+ `? `* `+ `> `< `&
+ `~ `! `!= `== `<< `>>
+ `+= `&& `|| `<= `>=
+ `@ `-= `-> `={ `${ `@{
+end
+
+def embedded_host
+ [`host `( string `, uint `) `={ TL: host::tok* host::`}=] :Expr
+| [`host `( string `, uint `) `${ TL: host::tok* host::`}$] :Stmt
+| [`host `( string `, uint `) `@{ TL: host::tok* host::`}@] :Bare
+
+def type
+ [ident] :Ident
+| [ident ident] :Ident2
+| [`uint] :Uint
+| [`s8] :S8
+| [`s16] :S16
+| [`s32] :S32
+| [`s64] :S64
+| [`s128] :S128
+
+def expr_factor
+ [embedded_host] :EmbeddedHost
+| [ident] :Ident
+| [ident `[ expr `]] :ArraySub
+| [ident `[ expr `] `. Field: ident] :ArraySubField
+| [`offset `( ident `, expr `)] :Offset
+| [`deref `( ident `, expr `)] :Deref
+| [number] :Number
+| [`TRUE] :True
+| [`FALSE] :False
+| [`nil] :Nil
+| [hex_number] :HexNumber
+| [string] :String
+| [embedded_host `-> expr_factor] :Access
+| [`( expr `)] :Paren
+| [`cast `( type `) expr_factor] :Cast
+
+def lvalue
+ [embedded_host]
+| [ident]
+| [ident `[ expr `]]
+| [ident `[ expr `] `. ident]
+| [embedded_host `-> lvalue]
+
+def expr_factor_op
+ [`! expr_factor_op]
+| [`~ expr_factor_op]
+| [expr_factor]
+
+def expr_bitwise
+ [expr_bitwise `& expr_factor_op]
+| [expr_factor_op]
+
+def expr_mult
+ [expr_mult `* expr_bitwise]
+| [expr_bitwise]
+
+def add_op
+ [`+] | [`-]
+
+def expr_add
+ [expr_add add_op expr_mult]
+| [expr_mult]
+
+def shift_op
+ [`<<] | [`>>]
+
+def expr_shift
+ [expr_shift shift_op expr_add]
+| [expr_add]
+
+def test_op
+ [`<] | [`>] | [`<=] | [`>=] |
+ [`==] | [`!=] | [`&&] | [`||]
+
+def expr_test
+ [expr_test test_op expr_shift]
+| [expr_shift]
+
+def expr
+ [expr_test]
+
+def sint
+ [uint]
+| [`- uint]
+
+def number
+ [`u `( uint `)] :Unsigned
+| [`c `( uint `)] :Char
+| [sint] :Number
+
+def comma_num
+ [`, number]
+
+def num_list
+ [number comma_num*]
+| []
+
+def static_array
+ [`array type ident `( number `, number `) `= `{ num_list `} `;]
+
+def static_value
+ [`value type ident `= number `;]
+
+def break_label
+ [ident `: `:]
+
+def while_stmt
+ [break_label? `while `( expr `) stmt]
+
+def else_if_clause
+ [`else `if `( expr `) stmt]
+
+def else_clause
+ [`else stmt]
+
+def if_stmt [
+ `if `( expr `) stmt
+ else_if_clause* else_clause?
+]
+
+def match_stmt
+ [`match `( E: expr `) `{ P: pat_block* D: default_block? `}]
+
+def pat_block
+ [`pat expr `{ stmt* `}]
+
+def switch_stmt
+ [`switch `( expr `) `{ stmt* `}]
+
+def case_block
+ [`case expr `{ stmt* `}]
+
+def default_block
+ [`default `{ stmt* `}]
+
+def case_label
+ [`case expr `:]
+
+def goto_label
+ [ident `:]
+
+def opt_init
+ [`= expr]
+| []
+
+def opt_ptr
+ [`*]
+| []
+
+def opt_const
+ [`const]
+| []
+
+def declaration
+ [opt_const type ident opt_init `;]
+
+def index_stmt
+ [`index type ident opt_init`;]
+
+def export_stmt
+ [`export type ident number `;]
+
+def goto_stmt
+ Id: int
+ [`goto ident `;]
+
+def fallthrough
+ [`fallthrough `;]
+
+def break_stmt
+ [`break ident? `;]
+
+def continue_stmt
+ [`continue ident? `;]
+
+def block
+ [`{ StmtList: stmt* `}]
+
+def expr_stmt
+ [expr `;]
+
+def assign_op
+ [`=] | [`+=] | [`-=]
+
+def assign_stmt
+ [LValue: lvalue assign_op expr `;]
+
+def stmt
+ [embedded_host]
+| [static_array]
+| [static_value]
+| [declaration]
+| [index_stmt]
+| [export_stmt]
+| [assign_stmt]
+| [expr_stmt]
+| [while_stmt]
+| [if_stmt]
+| [match_stmt]
+| [switch_stmt]
+| [case_block]
+| [default_block]
+| [case_label]
+| [goto_label]
+| [goto_stmt]
+| [fallthrough]
+| [break_stmt]
+| [continue_stmt]
+| [block]
+
+token bom / 0xEF 0xBB 0xBF /
+
+def opt_bom
+ [bom] :Bom
+| []
+
+def start
+ [opt_bom stmt*]
diff --git a/src/cgil/rlhc-c.lm b/src/cgil/rlhc-c.lm
new file mode 100644
index 00000000..dfc24d1d
--- /dev/null
+++ b/src/cgil/rlhc-c.lm
@@ -0,0 +1,462 @@
+include 'ril.lm'
+
+namespace c_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 c_out
+ [_IN_ _EX_ item*]
+end
+
+namespace c_gen
+ global _: parser<c_out::c_out>
+
+ void tok_list( TL: host::tok* )
+ {
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case Stmt {
+ << "{
+ " [stmt_list( StmtList )]
+ "}
+ }
+ case Expr {
+ << "([expr( Expr )])"
+ }
+ case Escape {
+ Str: str = $escape
+ << "[Str.suffix( 1 )]"
+ }
+ default {
+ << [Tok]
+ }
+ }
+ }
+
+ void embedded_host( EmbeddedHost: embedded_host )
+ {
+ switch EmbeddedHost
+ case Expr
+ {
+ << "([tok_list( TL )])"
+ }
+ case Stmt
+ {
+ << "{
+ " [tok_list( TL )]
+ "}
+ }
+ case Bare
+ {
+ << [tok_list( TL )]
+ }
+ }
+
+ void expr_factor( ExprFactor: expr_factor )
+ {
+ switch ExprFactor
+ case [EH: embedded_host]
+ {
+ << [embedded_host( EH )]
+ }
+ case Paren
+ {
+ << "([expr( expr )])"
+ }
+ case ArraySub
+ {
+ << "[ident]\[[expr( expr )]\]"
+ }
+ case ArraySubField
+ {
+ << "[ident]\[[expr( expr )]\].[Field]"
+ }
+ case Offset
+ {
+ << "[ident] + [expr( expr )]"
+ }
+ case Deref
+ {
+ << "(*( [expr(expr)] ))
+ }
+ case [`TRUE]
+ {
+ << "1"
+ }
+ case [`FALSE]
+ {
+ << "1"
+ }
+ case [N: `nil]
+ {
+ << "0"
+ }
+ case [Number: number]
+ {
+ number( Number )
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast `( T: type `) F: expr_factor]
+ {
+ << "( [type( T )] ) [expr_factor( F )]"
+ }
+ default {
+ # Catches cases not specified
+ << [ExprFactor]
+ }
+ }
+
+ void lvalue( ExprFactor: lvalue )
+ {
+ switch ExprFactor
+ case [EH: embedded_host]
+ {
+ << [embedded_host( EH )]
+ }
+ case [ident O: `[ TL: expr C: `]]
+ {
+ << [ident O expr( TL ) C]
+ }
+ case [I: ident `[ E: expr `] `. F: ident]
+ {
+ << "[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
+ << [ExprFactor]
+ }
+ }
+
+ void expr_factor_op( ExprFactorOp: expr_factor_op )
+ {
+ switch ExprFactorOp
+ case [B: `! expr_factor_op]
+ {
+ << ['!' expr_factor_op( _expr_factor_op )]
+ }
+ case [T: `~ expr_factor_op]
+ {
+ << ['~' expr_factor_op( _expr_factor_op )]
+ }
+ case [expr_factor]
+ {
+ << [expr_factor( expr_factor )]
+ }
+ }
+
+ void expr_bitwise( ExprBitwise: expr_bitwise )
+ {
+ switch ExprBitwise
+ case [expr_bitwise A: `& expr_factor_op]
+ {
+ << [expr_bitwise( _expr_bitwise ) A expr_factor_op( expr_factor_op )]
+ }
+ case [expr_factor_op]
+ {
+ << [expr_factor_op( expr_factor_op )]
+ }
+ }
+
+ void expr_mult( ExprMult: expr_mult )
+ {
+ switch ExprMult
+ case [expr_mult T: `* expr_bitwise]
+ {
+ << [expr_mult( _expr_mult ) T expr_bitwise( expr_bitwise )]
+ }
+ case [expr_bitwise]
+ {
+ << [expr_bitwise( expr_bitwise )]
+ }
+ }
+
+ void expr_add( ExprAdd: expr_add )
+ {
+ switch ExprAdd
+ case [expr_add Op: add_op expr_mult]
+ {
+ << [expr_add( _expr_add ) Op expr_mult( expr_mult )]
+ }
+ case [expr_mult]
+ {
+ << [expr_mult( expr_mult )]
+ }
+ }
+
+ void expr_shift( ExprShift: expr_shift )
+ {
+ switch ExprShift
+ case [expr_shift Op: shift_op expr_add]
+ {
+ << [expr_shift( _expr_shift ) Op expr_add( expr_add )]
+ }
+ case [expr_add]
+ {
+ << [expr_add( expr_add )]
+ }
+ }
+
+ void expr_test( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ << [expr_test( _expr_test ) Op expr_shift( expr_shift )]
+ }
+ case [expr_shift]
+ {
+ << [expr_shift( expr_shift )]
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case S8
+ << ['signed char ']
+ case S16
+ << ['short ']
+ case S32
+ << ['int ']
+ case S64
+ << ['long ']
+ case S128
+ << ['long long ']
+ case "uint"
+ << ['unsigned int ']
+ default
+ << [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case Unsigned
+ << "[uint]u"
+ default
+ << [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ << "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ << [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ << "static const [type(A.type)] "
+ "[A.ident] \[\] = { [num_list(A.num_list)] };
+ }
+ case [V: static_value] {
+ << "static const [V.type] [V.ident] = [V.number];
+ }
+ case [
+ `if `( IfExpr: expr `)
+ IfStmt: stmt
+ ElseIfClauseList: else_if_clause*
+ ElseClauseOpt: else_clause?
+ ] {
+ << "if ( [expr(IfExpr)] )
+ << " [stmt(IfStmt)]
+
+ for ElseIfClause: else_if_clause in repeat( ElseIfClauseList ) {
+ match ElseIfClause
+ [`else `if `( ElseIfExpr: expr `) ElseIfStmt: stmt]
+
+ << "else if ( [expr(ElseIfExpr)] )
+ " [stmt(ElseIfStmt)]
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ << "else
+ << " [stmt(ElseStmt)]
+ }
+ }
+ case [`while `( WhileExpr: expr `) WhileStmt: stmt] {
+ << "while ( [expr(WhileExpr)] )
+ " [stmt(WhileStmt)]
+ }
+ case [M: match_stmt] {
+ << "switch ( [expr(M.E)] ) {
+
+ for PB: pat_block in repeat( M.P ) {
+ << "case [expr( PB.expr )]:
+ "[stmt_list( PB._repeat_stmt )]
+ "break;
+ }
+
+ if match M.D [D: default_block] {
+ << "default:
+ "[stmt_list( D._repeat_stmt )]
+ "break;
+ }
+
+ << "}
+ }
+ case [`switch `( SwitchExpr: expr `) `{ StmtList: stmt* `}] {
+ << "switch ( [expr(SwitchExpr)] ) {
+ " [stmt_list(StmtList)]
+ "}
+ }
+ case [ES: expr_stmt] {
+ << "[expr(ES.expr)];
+ }
+ case [B: block] {
+ << "{
+ " [stmt_list(B.StmtList)]
+ "}
+ }
+ case [
+ OptConst: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ << "[OptConst] [type(Type)] [Ident]"
+
+ if match OptInit [`= Init: expr] {
+ << " = [expr(Init)]
+ }
+
+ << ";
+ }
+ case [Export: export_stmt]
+ {
+ << "#define [Export.ident] [number(Export.number)]
+ }
+ case [fallthrough]
+ {
+ # Nothing needed here.
+ # C falls through by default.
+ }
+ case [Index: index_stmt]
+ {
+ << "const [type(Index.type)] *[Index.ident]
+
+ if match Index.opt_init [E: `= expr] {
+ << [E expr(Index.opt_init.expr)]
+ }
+
+ << ";
+ }
+ case [CB: case_block]
+ {
+ << "case [expr( CB.expr )]:
+ "[stmt_list( CB._repeat_stmt )]
+ "break;
+ }
+ case [DB: default_block]
+ {
+ << "default:
+ "[stmt_list( DB._repeat_stmt )]
+ "break;
+ }
+ case [CL: case_label]
+ {
+ << "case [expr( CL.expr )]:
+ }
+ case [AS: assign_stmt]
+ {
+ << "[lvalue(AS.LValue) AS.assign_op expr(AS.expr)];
+ }
+ default {
+ # catches unspecified cases
+ << [Stmt]
+ }
+ }
+
+ void stmt_list( StmtList: stmt* )
+ {
+ for Stmt: stmt in repeat( StmtList )
+ stmt( Stmt )
+ }
+
+ void trans( Output: stream, Start: start )
+ {
+ _ = new parser<c_out::c_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ CO: c_out::c_out = _->finish()
+
+ if CO {
+ send Output
+ [CO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [_->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ c_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-crack.lm b/src/cgil/rlhc-crack.lm
new file mode 100644
index 00000000..bebe7cd5
--- /dev/null
+++ b/src/cgil/rlhc-crack.lm
@@ -0,0 +1,536 @@
+include 'ril.lm'
+
+namespace crack_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 ) * "'" |
+ "`" ( [^`\\] | '\\' any ) * "`"
+ /
+
+ ignore
+ /[ \t\v\r\n]+/
+ end
+
+ def item
+ [comment]
+ | [id]
+ | [number]
+ | [symbol]
+ | [string]
+ | [`{ _IN_ item* _EX_ `} ]
+
+ def crack_out
+ [_IN_ _EX_ item*]
+end
+
+namespace crack_gen
+
+ global Parser: parser<crack_out::crack_out>
+
+ void tok_list( TL: host::tok* )
+ {
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case [host::`${ StmtList: stmt* host::`}$] {
+ send Parser
+ "if ( 1 ) {
+ " [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
+ "if ( 1 ) {
+ " [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 [`( E: expr `)]
+ {
+ send Parser
+ "([expr(E)])"
+ }
+ case [I: ident `[ E: expr `]]
+ {
+ send Parser
+ "[I]\[[expr( E )]\]"
+ }
+ case [`offset `( ident `, expr `)]
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case [`deref `( ident `, expr `)]
+ {
+ send Parser
+ [ ExprFactor.ident '[' expr( ExprFactor.expr ) ']']
+ }
+ case [`TRUE]
+ {
+ send Parser "1"
+ }
+ case [`FALSE]
+ {
+ send Parser "1"
+ }
+ case [N: `nil]
+ {
+ send Parser "0"
+ }
+ case [Number: number]
+ {
+ number( Number )
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast `( T: type `) F: expr_factor]
+ {
+ send Parser
+ "[type( T )] ( [expr_factor( F )] )"
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['int16 ']
+ case "s16"
+ send Parser ['int16 ']
+ case "s32"
+ send Parser ['int32 ']
+ case "s64"
+ send Parser ['int64 ']
+ case "s128"
+ send Parser ['long long ']
+ case "uint"
+ send Parser ['uint32 ']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]u"
+ case [`c `( uint `) ]
+ send Parser "[Number.uint]"
+ default
+ send Parser [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [Array: static_array] {
+ send Parser
+ "const array\[[type(Array.type)]\] "
+ "[Array.ident] = \[ [num_list(Array.num_list)] \];
+ }
+ case [Value: static_value] {
+ send Parser
+ "const [Value.type] [Value.ident] = [Value.number];
+ }
+ case [
+ `if `( IfExpr: expr `) IfStmt: stmt
+ ElseIfClauseList: else_if_clause* ElseClauseOpt: else_clause?
+ ] {
+ send Parser
+ "if ( [expr(IfExpr)] )
+ " [flow_stmt(IfStmt)]
+
+ for ElseIfClause: else_if_clause in repeat( ElseIfClauseList ) {
+ match ElseIfClause
+ ['else if (' ElseIfExpr: expr ')' ElseIfStmt: stmt]
+
+ send Parser
+ "else if ( [expr(ElseIfExpr)] )
+ " [flow_stmt(ElseIfStmt)]
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ send Parser
+ "else
+ " [flow_stmt(ElseStmt)]
+ }
+ }
+ case [`while `( WhileExpr: expr `) WhileStmt: stmt] {
+ send Parser
+ "while ( [expr(WhileExpr)] )
+ " [flow_stmt(WhileStmt)]
+ }
+ case [`switch `( SwitchExpr: expr `) `{ StmtList: stmt* `}] {
+
+ require StmtList
+ [`case E1: expr `{ Inner: stmt* `} Rest: stmt*]
+
+ send Parser
+ "if ( [expr(SwitchExpr)] == [expr(E1)] ) {
+ " [stmt_list(Inner)]
+ "}
+
+ for S: stmt in repeat(Rest) {
+ switch S
+ case [`case E1: expr `{ Inner: stmt* `}]
+ {
+ send Parser
+ "else if ( [expr(SwitchExpr)] == [expr(E1)] ) {
+ " [stmt_list(Inner)]
+ "}
+ }
+ case
+ [`default `{ Inner: stmt* `}]
+ {
+ send Parser
+ "else {
+ " [stmt_list(Inner)]
+ "}
+ }
+ }
+
+ send Parser
+ ";
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr(ExprExpr) Semi]
+ }
+ case [`{ TL: stmt* `}] {
+ send Parser
+ "if ( 1 ) {
+ " [stmt_list(TL)]
+ "}
+ }
+ case [
+ TypeList: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [TypeList type(Type) Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "#define [Export.ident] [number(Export.number)]
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "int [Index.ident]
+
+ if match Index.opt_init [E: `= expr] {
+ send Parser
+ [E expr(Index.opt_init.expr)]
+ }
+ else {
+ send Parser
+ " = 0"
+ }
+
+ 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 [case_label]
+ {
+ send Parser
+ "case [expr( Stmt.case_label.expr )]:
+ }
+ case [AS: assign_stmt]
+ {
+ send Parser
+ "[lvalue(AS.LValue) AS.assign_op expr(AS.expr)];
+ }
+ default {
+ # catches unspecified cases
+ send Parser [Stmt]
+ }
+ }
+
+ void flow_stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [`{ TL: stmt* `}] {
+ send Parser
+ "{
+ " [stmt_list(TL)]
+ "}
+ }
+ default {
+ stmt( Stmt )
+ }
+ }
+
+ void stmt_list( StmtList: stmt* )
+ {
+ for Stmt: stmt in repeat( StmtList )
+ stmt( Stmt )
+ }
+
+ void trans( Output: stream, Start: start )
+ {
+ Parser = new parser<crack_out::crack_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ CO: crack_out::crack_out = Parser->finish()
+
+ if CO {
+ send Output
+ [CO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ crack_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-csharp.lm b/src/cgil/rlhc-csharp.lm
new file mode 100644
index 00000000..078157c5
--- /dev/null
+++ b/src/cgil/rlhc-csharp.lm
@@ -0,0 +1,480 @@
+include 'ril.lm'
+
+namespace csharp_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 csharp_out
+ [_IN_ _EX_ item*]
+end
+
+namespace csharp_gen
+
+ global Parser: parser<csharp_out::csharp_out>
+
+ 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( EH: embedded_host )
+ {
+ switch EH
+ 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' '(' ident ',' expr ')']
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case ['deref' '(' ident ',' expr ')']
+ {
+ send Parser
+ [ ExprFactor.ident '[' expr( ExprFactor.expr ) ']']
+ }
+ case [T: `TRUE]
+ {
+ T.data = 'true'
+ send Parser [T]
+ }
+ case [F: `FALSE]
+ {
+ F.data = 'false'
+ send Parser [F]
+ }
+ case [N: `nil]
+ {
+ N.data = '0'
+ 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: type Close: `) expr_factor]
+ {
+ send Parser [Open]
+ type( Type )
+ send Parser [Close]
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['sbyte ']
+ case "s16"
+ send Parser ['short ']
+ case "s32"
+ send Parser ['int ']
+ case "s64"
+ send Parser ['long ']
+ case "s128"
+ send Parser ['long long ']
+ case "uint"
+ send Parser ['uint ']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`c `( uint `) ] {
+ Str: str = $Number.uint
+ send Parser "'\\u[sprintf( "%04x", Str.atoi() )]'"
+ }
+ case [`u `( uint `) ] {
+ send Parser [$Number.uint]
+ }
+ default {
+ send Parser [$Number.sint]
+ }
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ send Parser
+ "static readonly [type(A.type)] \[\]"
+ "[A.ident] = { [num_list( A.num_list )] };
+ }
+ case [V: static_value] {
+ send Parser
+ "static readonly [V.type] [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
+ [L stmt_list(TL) R]
+ }
+ case [
+ TypeList: opt_const Type: type Ident: ident
+ OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [TypeList type(Type) Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "#define [Export.ident] [Export.number]
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "int [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 [case_label]
+ {
+ send Parser
+ "case [expr( Stmt.case_label.expr )]:
+ }
+ 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<csharp_out::csharp_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ CSO: csharp_out::csharp_out = Parser->finish()
+
+ if CSO {
+ send Output
+ [CSO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ csharp_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-d.lm b/src/cgil/rlhc-d.lm
new file mode 100644
index 00000000..2a047e68
--- /dev/null
+++ b/src/cgil/rlhc-d.lm
@@ -0,0 +1,511 @@
+include 'ril.lm'
+
+namespace d_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 d_out
+ [_IN_ _EX_ item*]
+end
+
+namespace d_gen
+
+ global Parser: parser<d_out::d_out>
+
+ global HasDefault: list<int> = new list<int>()
+
+ void pushHasDef( H: int )
+ {
+ HasDefault->push( H )
+ }
+
+ int popHasDef()
+ {
+ return HasDefault->pop()
+ }
+
+ 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 `( ident `, expr `)]
+ {
+ send Parser
+ "& [ExprFactor.ident] \[ [expr(ExprFactor.expr)] \]
+ }
+ case
+ [`deref `( ident `, expr `)]
+ {
+ send Parser
+ "(*( [expr(ExprFactor.expr)] ))
+ }
+ case
+ [T: `TRUE]
+ {
+ T.data = '1'
+ send Parser [T]
+ }
+ case
+ [F: `FALSE]
+ {
+ F.data = '0'
+ send Parser [F]
+ }
+ case
+ [N: `nil]
+ {
+ N.data = 'null'
+ 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: type Close: `) expr_factor]
+ {
+ send Parser ['cast' Open]
+ type( Type )
+ send Parser [Close]
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['byte ']
+ case "s16"
+ send Parser ['short ']
+ case "s32"
+ send Parser ['int ']
+ case "s64"
+ send Parser ['long ']
+ case "s128"
+ send Parser ['long long ']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]u"
+ default
+ send Parser [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host(EH)]
+ }
+ case [A: static_array] {
+ send Parser
+ "static const [type(A.type)]\[\] "
+ "[A.ident] = \[ [num_list( A.num_list )] \];
+ }
+ case [V: static_value] {
+ send Parser
+ "static const [V.type] [V.ident] = [V.number];
+ }
+ case [
+ `if `( IfExpr: expr `) 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* `}] {
+ pushHasDef( 0 )
+
+ send Parser
+ "switch ( [expr(SwitchExpr)] ) {
+ " [stmt_list(StmtList)]
+
+ if ( popHasDef() == 0 ) {
+ send Parser
+ " default: break;
+ }
+
+ send Parser
+ "}
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr( ExprExpr ) Semi]
+ }
+ case [L: `{ TL: stmt* R: `}] {
+ send Parser
+ [L stmt_list( TL ) R]
+ }
+ case [
+ OptConst: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ if match OptConst ['const'] {
+ send Parser
+ "const( [type( Type )] )
+ }
+ else {
+ type( Type )
+ }
+
+ send Parser [Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser [Semi]
+ }
+ 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;
+
+ popHasDef()
+ pushHasDef( 1 )
+ }
+ case [case_label]
+ {
+ send Parser
+ "case [expr( Stmt.case_label.expr )]:
+ }
+ case [export_stmt]
+ {
+ send Parser
+ "static const [type(Stmt.export_stmt.type)] "
+ "[Stmt.export_stmt.ident] = [number(Stmt.export_stmt.number)];
+ }
+ case ['fallthrough' ';']
+ {
+ send Parser "goto case;"
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "const([type(Index.type)]) *[Index.ident]"
+
+ if match Index.opt_init [E: `= expr] {
+ send Parser
+ [E expr(Index.opt_init.expr)]
+ }
+
+ send Parser ";
+ }
+ 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<d_out::d_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ DO: d_out::d_out = Parser->finish()
+
+ if DO {
+ send Output
+ [DO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ d_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-go.lm b/src/cgil/rlhc-go.lm
new file mode 100644
index 00000000..b8353d10
--- /dev/null
+++ b/src/cgil/rlhc-go.lm
@@ -0,0 +1,454 @@
+include 'ril.lm'
+
+namespace out_go
+ 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 out_go
+ [_IN_ _EX_ item*]
+end
+
+
+
+namespace go_gen
+
+ global _: parser<out_go::out_go>
+
+ void tok_list( TL: host::tok* )
+ {
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case Stmt {
+ << "{
+ " [stmt_list( StmtList )]
+ "}
+ }
+ case Expr {
+ << "([expr( Expr )])"
+ }
+ case Escape {
+ Str: str = $Tok
+ << "[Str.suffix( 1 )]"
+ }
+ default {
+ << [Tok]
+ }
+ }
+ }
+
+ void embedded_host( EmbeddedHost: embedded_host )
+ {
+ switch EmbeddedHost
+ case Expr
+ {
+ << ['(' tok_list( TL ) ')']
+ }
+ case Stmt
+ {
+ << ['{' tok_list( TL ) '}\n']
+ }
+ case Bare
+ {
+ << [tok_list( TL )]
+ }
+ }
+
+ void expr_factor( ExprFactor: expr_factor )
+ {
+ switch ExprFactor
+ case EmbeddedHost
+ {
+ << [embedded_host(embedded_host)]
+ }
+ case Paren
+ {
+ << ['( ' expr(expr) ' )']
+ }
+ case ArraySub
+ {
+ << [ident '[ ' expr( expr ) ' ]']
+ }
+ case Offset
+ {
+ << "int([expr(expr )])
+ }
+ case Deref
+ {
+ << [ident '[ ' expr( expr ) ' ]' ]
+ }
+ case True
+ {
+ << "true"
+ }
+ case False
+ {
+ << "false"
+ }
+ case Nil
+ {
+ << "0"
+ }
+ case Access
+ {
+ embedded_host(embedded_host)
+ expr_factor(_expr_factor)
+ }
+ case Cast
+ {
+ << [type(type) '( ' expr_factor(_expr_factor) ' )' ]
+ }
+ default {
+ # Catches cases not specified
+ << [ExprFactor]
+ }
+ }
+
+ void lvalue( ExprFactor: lvalue )
+ {
+ switch ExprFactor
+ case [EH: embedded_host]
+ {
+ << [embedded_host(EH)]
+ }
+ case [ident `[ TL: expr `]]
+ {
+ << [ident '[' expr( TL ) ']']
+ }
+ case [E1: embedded_host `-> E2: lvalue]
+ {
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ default {
+ # Catches cases not specified
+ << [ExprFactor]
+ }
+ }
+
+ void expr_factor_op( ExprFactorOp: expr_factor_op )
+ {
+ switch ExprFactorOp
+ case [B: `! expr_factor_op]
+ {
+ << ['! ' expr_factor_op( _expr_factor_op )]
+ }
+ case [T: `~ expr_factor_op]
+ {
+ << ['^ ' expr_factor_op( _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( _expr_bitwise ) ' & ' expr_factor_op( 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( _expr_mult ) ' * ' expr_bitwise( expr_bitwise )]
+ }
+ case [expr_bitwise]
+ {
+ << [expr_bitwise( expr_bitwise )]
+ }
+ }
+
+ void expr_add( ExprAdd: expr_add )
+ {
+ switch ExprAdd
+ case [expr_add Op: add_op expr_mult]
+ {
+ << [expr_add( _expr_add ) ' ' Op ' ' expr_mult( 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( _expr_shift ) ' ' Op ' ' expr_add( expr_add )]
+ }
+ case [expr_add]
+ {
+ << [expr_add( expr_add )]
+ }
+ }
+
+ void expr_test( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ << [expr_test( _expr_test ) ' ' Op ' ' expr_shift( expr_shift )]
+ }
+ case [expr_shift]
+ {
+ << [expr_shift( ExprTest.expr_shift )]
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case S8
+ << ['int8']
+ case S16
+ << ['int16']
+ case S32
+ << ['int32']
+ case S64
+ << ['int64']
+ case S128
+ << ['long long']
+ default
+ << [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case Unsigned
+ << [uint]
+ default
+ << [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ number( NumList.number )
+ for CommaNum: comma_num in NumList {
+ << [', ' number( CommaNum.number )]
+ }
+ }
+
+ # Go must have {} around if and for statements. We strip any blocks from
+ # these statments and force our own.
+ void strip_block_stmt( Stmt: stmt )
+ {
+ if match Stmt [`{ StmtList: stmt* `}]
+ stmt_list(StmtList)
+ else
+ stmt( Stmt )
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ << [embedded_host(EH)]
+ }
+ case [A: static_array] {
+ << "var [A.ident] = \[\] "
+ "[type(A.type)] { [num_list(A.num_list)] }
+ }
+ case [V: static_value] {
+ << "var [V.ident] [type(V.type)] = [V.number]
+ "var _ = [V.ident]
+ }
+ case [
+ 'if' O: `( IfExpr: expr C: `) IfStmt: stmt
+ ] {
+ # if-statements with only the if clause can go out as an if.
+ << "if [expr(IfExpr)] {
+ " [strip_block_stmt(IfStmt)]
+ "}
+ }
+ case [
+ 'if' O: `( IfExpr: expr C: `) IfStmt: stmt
+ ElseIfClauseList: else_if_clause* ElseClauseOpt: else_clause?
+ ] {
+ # If the if-statement has more than just an if clause it goes out as a switch.
+ << "if [expr( IfExpr )] {
+ " [strip_block_stmt( IfStmt )]
+
+ for ElseIfClause: else_if_clause in repeat( ElseIfClauseList ) {
+ match ElseIfClause
+ ['else if (' ElseIfExpr: expr ')' ElseIfStmt: stmt]
+
+ << "} else if [expr(ElseIfExpr)] {
+ " [strip_block_stmt(ElseIfStmt)]
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ << "} else {
+ " [strip_block_stmt(ElseStmt)]
+ }
+
+ << "}
+ }
+ case ["while ( TRUE )" WhileStmt: stmt] {
+ << "for {
+ " [strip_block_stmt(WhileStmt)]
+ "}
+ }
+ case ['while' '(' WhileExpr: expr ')' WhileStmt: stmt] {
+ << "for [expr(WhileExpr)] {
+ " [strip_block_stmt(WhileStmt)]
+ "}
+ }
+ case ['switch' '(' SwitchExpr: expr ')' '{' StmtList: stmt* '}'] {
+ << "switch [expr(SwitchExpr)] {
+ " [stmt_list(StmtList)]
+ "}
+ }
+ case [ExprExpr: expr `;] {
+ << [expr(ExprExpr) ';']
+ }
+ case [B: block] {
+ << "{
+ " [stmt_list(B.StmtList)]
+ "}
+ }
+ case [D: declaration]
+ {
+ << "var [D.ident] [type(D.type)]"
+
+ if match D.opt_init ['=' Expr: expr] {
+ << " = [expr(Expr)]"
+ }
+
+ << ['\n']
+ }
+ case [ES: export_stmt]
+ {
+ << "#define [ES.ident] [number(ES.number)]
+ }
+ case [fallthrough]
+ {
+ << "fallthrough
+ }
+ case [Index: index_stmt]
+ {
+ << "var [Index.ident] int"
+
+ if match Index.opt_init ['=' Expr: expr] {
+ << " = [expr(Expr)]"
+ }
+
+ << ['\n']
+ }
+ case [CB: case_block]
+ {
+ << "case [expr( CB.expr )]:
+ " [stmt_list( CB._repeat_stmt )]
+ }
+ case [DB: default_block]
+ {
+ << "default:
+ " [stmt_list( DB._repeat_stmt )]
+ }
+ case [CL: case_label]
+ {
+ << "case [expr( CL.expr )]:
+ }
+ case [AS: assign_stmt]
+ {
+ << "[lvalue(AS.LValue) AS.assign_op expr(AS.expr)];
+ }
+ default {
+ # catches unspecified cases
+ << "[Stmt]
+ }
+ }
+
+ void stmt_list( StmtList: stmt* )
+ {
+ for Stmt: stmt in repeat( StmtList )
+ stmt( Stmt )
+ }
+
+ void trans( Output: stream, Start: start )
+ {
+ _ = new parser<out_go::out_go>()
+ Input: _input = _->gets()
+ Input->auto_trim(true)
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ GO: out_go::out_go = _->finish()
+
+ if GO {
+ send Output
+ [GO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [_->error]
+ }
+
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ go_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-java.lm b/src/cgil/rlhc-java.lm
new file mode 100644
index 00000000..a458369f
--- /dev/null
+++ b/src/cgil/rlhc-java.lm
@@ -0,0 +1,504 @@
+include 'ril.lm'
+
+namespace java_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 java_out
+ [_IN_ _EX_ item*]
+end
+
+namespace java_gen
+
+ global Parser: parser<java_out::java_out>
+
+ 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( EH: embedded_host )
+ {
+ switch EH
+ 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' '(' ident ',' expr ')']
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case
+ ['deref' '(' ident ',' expr ')']
+ {
+ send Parser
+ [ ExprFactor.ident '[' expr( ExprFactor.expr ) ']']
+ }
+ case
+ [T: `TRUE]
+ {
+ T.data = 'true'
+ send Parser [T]
+ }
+ case
+ [F: `FALSE]
+ {
+ F.data = 'false'
+ send Parser [F]
+ }
+ case
+ [N: `nil]
+ {
+ N.data = '0'
+ 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: type Close: `) expr_factor]
+ {
+ send Parser [Open]
+ type( Type )
+ send Parser [Close]
+ expr_factor( ExprFactor._expr_factor )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['byte ']
+ case "s16"
+ send Parser ['short ']
+ case "s32"
+ send Parser ['int ']
+ case "s64"
+ send Parser ['long ']
+ case "s128"
+ send Parser ['long long ']
+ case "uint"
+ send Parser ['int ']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]"
+ default
+ send Parser [Number]
+ }
+
+ void java_num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ send Parser
+ "private static [type(A.type)] "
+ "[A.ident] \[\] = { [java_num_list(A.num_list)] };
+ }
+ case [V: static_value] {
+ send Parser
+ "private static [V.type] [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 [BL: break_label? 'while' '(' WhileExpr: expr ')' '{' StmtList: stmt* '}' ] {
+ if match BL [bl: break_label]
+ send Parser "[bl.ident]: "
+
+ send Parser
+ "while ( [expr(WhileExpr)] ) {
+ " [stmt_list(StmtList)]
+ "}
+ }
+ 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
+ [TypeList type(Type) Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "static final char [Export.ident] = [number(Export.number)];
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "int [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<java_out::java_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ JO: java_out::java_out = Parser->finish()
+
+ if JO {
+ send Output
+ [JO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ java_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-js.lm b/src/cgil/rlhc-js.lm
new file mode 100644
index 00000000..29a61346
--- /dev/null
+++ b/src/cgil/rlhc-js.lm
@@ -0,0 +1,504 @@
+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<js_out::js_out>
+
+ 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' '(' ident ',' expr ')']
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case ['deref' '(' ident ',' expr ')']
+ {
+ send Parser [ExprFactor.ident]
+ if $ExprFactor.ident == 'data'
+ send Parser ['.charCodeAt(' expr( ExprFactor.expr ) ')']
+ else
+ send Parser ['[' expr( ExprFactor.expr ) ']']
+ }
+ 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<js_out::js_out>()
+
+ 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'
diff --git a/src/cgil/rlhc-julia.lm b/src/cgil/rlhc-julia.lm
new file mode 100644
index 00000000..72108994
--- /dev/null
+++ b/src/cgil/rlhc-julia.lm
@@ -0,0 +1,561 @@
+include 'ril.lm'
+
+namespace julia_out
+ token _IN_ /''/
+ token _EX_ /''/
+
+ lex
+ token comment /
+ '//' any* :> '\n' |
+ '/*' any* :>> '*/'
+ /
+
+ literal `function `end `while `if `else `elseif
+
+ 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 kw
+ [`function _IN_]
+ | [`while _IN_]
+ | [`if _IN_]
+ | [_EX_ `elseif _IN_]
+ | [_EX_ `else _IN_]
+ | [_EX_ `end]
+
+ def item
+ [comment]
+ | [kw]
+ | [id]
+ | [number]
+ | [symbol]
+ | [string]
+ | [`{ _IN_ item* _EX_ `} ]
+
+ def julia_out
+ [_IN_ _EX_ item*]
+end
+
+namespace julia_gen
+
+ global Parser: parser<julia_out::julia_out>
+
+ void tok_list( TL: host::tok* )
+ {
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case [host::`${ StmtList: stmt* host::`}$] {
+ send Parser
+ "begin
+ " [stmt_list( StmtList )]
+ "end
+ }
+ 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 [`( E: expr `)]
+ {
+ send Parser
+ "([expr(E)])"
+ }
+ case [I: ident `[ E: expr `]]
+ {
+ send Parser
+ "[I]\[1+([expr( E )])\]"
+ }
+ case [`offset `( ident `, expr `)]
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case [`deref `( I: ident `, E: expr `)]
+ {
+ send Parser
+ "[I]\[1+([ expr( E ) ])\]"
+ }
+ case [`TRUE]
+ {
+ send Parser "true"
+ }
+ case [`FALSE]
+ {
+ send Parser "false"
+ }
+ case [N: `nil]
+ {
+ send Parser "0"
+ }
+ case [Number: number]
+ {
+ number( Number )
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast `( T: type `) F: expr_factor]
+ {
+ send Parser
+ "convert([type( T )], [expr_factor( F )] )"
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[1+(' expr(E) ')]']
+ }
+ default {
+ # Catches cases not specified
+ send Parser [ExprFactor]
+ }
+ }
+
+ void lvalue( ExprFactor: lvalue )
+ {
+ switch ExprFactor
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [I: ident `[ E: expr `]]
+ {
+ send Parser
+ "[I]\[1+([expr( E )])\]"
+ }
+ case [E1: embedded_host `-> E2: lvalue]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[1+(' expr(E) ')]']
+ }
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['Int8']
+ case "u8"
+ send Parser ['UInt8']
+ case "s16"
+ send Parser ['Int16']
+ case "s32"
+ send Parser ['Int32']
+ case "s64"
+ send Parser ['Int64']
+ case "s128"
+ send Parser ['Int128']
+ case "uint"
+ send Parser ['UInt']
+ case "int"
+ send Parser ['Int']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]u"
+ default
+ send Parser [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ send Parser
+ "const [A.ident] = [type(A.type)]\[[num_list(A.num_list)]\]
+ }
+ case [V: static_value] {
+ send Parser
+ "const [V.ident] = [V.number]
+ }
+ # case [declaration]
+ case [
+ TypeList: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+ else {
+ send Parser
+ "= 0
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [
+ `if `( IfExpr: expr `) 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
+ "elseif [expr(ElseIfExpr)]
+ " [stmt(ElseIfStmt)]
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ send Parser
+ "else
+ " [stmt(ElseStmt)]
+ }
+
+ send Parser
+ "end
+ }
+ case [`while `( WhileExpr: expr `) WhileStmt: stmt] {
+ send Parser
+ "while [expr(WhileExpr)]
+ " [stmt(WhileStmt)]
+ "end
+ }
+ case [`switch `( SwitchExpr: expr `) `{ StmtList: stmt* `}] {
+
+ require StmtList
+ [`case E1: expr `{ Inner: stmt* `} Rest: stmt*]
+
+ send Parser
+ "if [expr(SwitchExpr)] == [expr(E1)]
+ " [stmt_list(Inner)]
+
+ for S: stmt in repeat(Rest) {
+ switch S
+ case [`case E1: expr `{ Inner: stmt* `}]
+ {
+ send Parser
+ "elseif [expr(SwitchExpr)] == [expr(E1)]
+ " [stmt_list(Inner)]
+ }
+ case
+ [`default `{ Inner: stmt* `}]
+ {
+ send Parser
+ "else
+ " [stmt_list(Inner)]
+ }
+ }
+
+ send Parser
+ "end
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr(ExprExpr)]
+ }
+ case [L: `{ TL: stmt* R: `}] {
+ send Parser
+ [stmt_list(TL)]
+ }
+ case [
+ TypeList: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [TypeList type(Type) Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser ";
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "#define [Export.ident] [number(Export.number)]
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "[Index.ident]"
+
+ if match Index.opt_init [E: `= expr] {
+ send Parser
+ [E expr(Index.opt_init.expr)]
+ }
+ else {
+ send Parser " = 0 "
+
+ }
+
+ send Parser ";
+ }
+ case [case_block]
+ {
+ send Parser
+ "@case [expr( Stmt.case_block.expr )] begin
+ "[stmt_list( Stmt.case_block._repeat_stmt )]
+ "end
+ }
+ case [default_block]
+ {
+ send Parser
+ "default:
+ "[stmt_list( Stmt.default_block._repeat_stmt )]
+ "break;
+ }
+ case [case_label]
+ {
+ send Parser
+ "@case [expr( Stmt.case_label.expr )]
+ }
+ case [L: goto_label]
+ {
+ send Parser
+ "@label [L.ident]
+ }
+ case [G: goto_stmt]
+ {
+ send Parser
+ "@goto [G.ident]
+ }
+ 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<julia_out::julia_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ CO: julia_out::julia_out = Parser->finish()
+
+ if CO {
+ send Output
+ [CO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ julia_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-main.lm b/src/cgil/rlhc-main.lm
new file mode 100644
index 00000000..f9abea7e
--- /dev/null
+++ b/src/cgil/rlhc-main.lm
@@ -0,0 +1,19 @@
+InputFile: str = argv->pop()
+OutputFile: str = argv->pop()
+
+#
+# Open input and parse
+#
+Input: stream = open( InputFile, "r" )
+parse Start: start[ Input ]
+if ( !Start ) {
+ print( error, '\n' )
+ exit(1)
+}
+
+#
+# Translate
+#
+Output: stream = open( OutputFile, "w" )
+trans( Output, Start )
+
diff --git a/src/cgil/rlhc-ocaml.lm b/src/cgil/rlhc-ocaml.lm
new file mode 100644
index 00000000..f68b61be
--- /dev/null
+++ b/src/cgil/rlhc-ocaml.lm
@@ -0,0 +1,609 @@
+include 'ril.lm'
+
+namespace ocaml_out
+ token _IN_ /''/
+ token _EX_ /''/
+
+ lex
+ token comment /
+ '(*' any* :>> '*)'
+ /
+
+ literal `begin `end `{ `}
+
+ token id
+ /[a-zA-Z_][a-zA-Z_0-9]* "'"? /
+
+ token number /
+ [0-9]+
+ /
+
+ token symbol /
+ '!' | '#' | '$' | '%' | '&' | '(' | ')' | '*' |
+ '+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' |
+ '=' | '>' | '?' | '@' | '[' | ']' | '^' | '|' |
+ '~' | '`' /
+
+ token string /
+ '"' ( [^"\\\n] | '\\' any ) * '"' |
+ "'" ( [^'\\\n] | '\\' any ) * "'"
+ /
+
+ ignore
+ /[ \t\v\r\n]+/
+ end
+
+ def item
+ [comment]
+ | [id]
+ | [number]
+ | [symbol]
+ | [string]
+ | [`begin _IN_ item* _EX_ `end ]
+ | [`{ _IN_ item* _EX_ `} ]
+
+ def ocaml_out
+ [_IN_ _EX_ item*]
+end
+
+namespace ml_gen
+
+ global StaticVarMap: map<str, str> = new map<str, str>()
+ global Parser: parser<ocaml_out::ocaml_out>
+
+ void tok_list( TL: host::tok* )
+ {
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case [host::`${ StmtList: stmt* host::`}$]
+ send Parser
+ "begin
+ "[stmt_list( StmtList )]
+ "end;
+ 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( EH: embedded_host )
+ {
+ switch EH
+ case [`host `( string `, uint `) `={ TL: host::tok* host::`}=]
+ {
+ send Parser
+ "([tok_list( TL )])"
+ }
+ case [`host `( string `, uint `) `${ TL: host::tok* host::`}$]
+ {
+ send Parser
+ "begin
+ "[tok_list( TL )]
+ "end;
+ }
+ 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 [`( TL: expr `)]
+ {
+ send Parser
+ "( [ expr(TL) ] )"
+ }
+ case [I: ident `[ TL: expr `]]
+ {
+ if ( StaticVarMap->find( $I ) || $I == 'stack' ) {
+ send Parser
+ "[ ExprFactor.ident ].([ expr( TL ) ])"
+ }
+ else {
+ send Parser
+ "[ ExprFactor.ident ].\[[ expr( TL ) ]\]"
+ }
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '.(' expr(E) ')']
+ }
+ case ['offset' '(' ident ',' expr ')']
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case ['deref' '(' I: ident ',' Expr: expr ')']
+ {
+ if ( $I == 'data' )
+ send Parser 'Char.code '
+
+ if ( StaticVarMap->find( $I ) ) {
+ send Parser
+ "[I].( [ expr( Expr ) ] )"
+ }
+ else {
+ send Parser
+ "[I].\[[ expr( Expr ) ]\]"
+ }
+ }
+ case [T: `TRUE]
+ {
+ T.data = 'true'
+ send Parser [T]
+ }
+ case [F: `FALSE]
+ {
+ F.data = 'false'
+ send Parser [F]
+ }
+ case [N: `nil]
+ {
+ N.data = '0'
+ send Parser [N]
+ }
+ case [Number: number]
+ {
+ number( Number )
+ }
+ case [I: ident] {
+ if ( StaticVarMap->find( $I ) ) {
+ send Parser
+ [^I]
+ }
+ else {
+ send Parser
+ "[^I].contents"
+ }
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast `( type `) expr_factor]
+ {
+ send Parser
+ [expr_factor( ExprFactor._expr_factor )]
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '.(' E ')']
+ }
+ 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 " lnot "
+ expr_factor_op( ExprFactorOp._expr_factor_op )
+ }
+ case [expr_factor]
+ {
+ expr_factor( ExprFactorOp.expr_factor )
+ }
+ }
+
+ void expr_bitwise( ExprBitwise: expr_bitwise )
+ {
+ switch ExprBitwise
+ case [L: expr_bitwise `& R: expr_factor_op]
+ {
+ send Parser
+ "[expr_bitwise( L )] land [expr_factor_op( R )]"
+ }
+ 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 )
+ switch Op
+ case [`<<]
+ send Parser " lsl "
+ default
+ send Parser " asr "
+ expr_add( ExprShift.expr_add )
+ }
+ case [expr_add]
+ {
+ expr_add( ExprShift.expr_add )
+ }
+ }
+
+ void expr_test( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ switch Op
+ case [`==]
+ send Parser "= "
+ default
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['char ']
+ case "s16"
+ send Parser ['short ']
+ case "s32"
+ send Parser ['int ']
+ case "s64"
+ send Parser ['long ']
+ case "s128"
+ send Parser ['long long ']
+ case "uint"
+ send Parser ['int ']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]u"
+ default
+ send Parser [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )]; "
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ StaticVarMap->insert( $A.ident, ' ' )
+ send Parser
+ "let [A.ident] : int array = \[|
+ " [num_list(A.num_list)]
+ "|\]
+ }
+ case [V: static_value] {
+ StaticVarMap->insert( $V.ident, ' ' )
+ send Parser
+ "let [V.ident] : [V.type] = [V.number]
+ }
+ case [
+ 'if' O: `( IfExpr: expr C: `) IfStmt: stmt
+ ElseIfClauseList: else_if_clause* ElseClauseOpt: else_clause?
+ ] {
+ send Parser
+ "if [expr(IfExpr)] then
+ "begin
+ " [stmt(IfStmt)]
+ "end
+
+ for ElseIfClause: else_if_clause in repeat( ElseIfClauseList ) {
+ match ElseIfClause
+ ['else if (' ElseIfExpr: expr ')' ElseIfStmt: stmt]
+
+ send Parser
+ "else if [expr(ElseIfExpr)] then
+ "begin
+ " [stmt(ElseIfStmt)]
+ "end
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ send Parser
+ "else
+ "begin
+ " [stmt(ElseStmt)]
+ "end
+ }
+
+ send Parser
+ ";"
+ }
+ case ['while' '(' WhileExpr: expr ')' WhileStmt: stmt] {
+ send Parser
+ "while [expr(WhileExpr)] do
+ " [stmt(WhileStmt)]
+ "done;
+ }
+ case ['switch' '(' SwitchExpr: expr ')' '{' StmtList: stmt* '}'] {
+ require StmtList
+ [`case E1: expr `{ Inner: stmt* `} Rest: stmt*]
+
+ send Parser
+ "if [expr(SwitchExpr)] = [expr(E1)] then
+ "begin
+ " [stmt_list(Inner)]
+ "end
+
+ for S: stmt in repeat(Rest) {
+ switch S
+ case [`case E1: expr `{ Inner: stmt* `}]
+ {
+ send Parser
+ "else if [expr(SwitchExpr)] = [expr(E1)] then
+ "begin
+ " [stmt_list(Inner)]
+ "end
+ }
+ case
+ [`default `{ Inner: stmt* `}]
+ {
+ send Parser
+ "else
+ "begin
+ " [stmt_list(Inner)]
+ "end
+ }
+ }
+
+ send Parser
+ ";
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr(ExprExpr) Semi]
+ }
+ case [L: `{ TL: stmt* R: `}] {
+ send Parser
+ "begin
+ "[stmt_list(TL)]
+ "end;
+ }
+ case [D: declaration] {
+ send Parser
+ "let [D.ident] : [type(D.type)] ref "
+
+ switch D.opt_init
+ case [E: `= expr] {
+ send Parser
+ "= ref ( [expr(D.opt_init.expr)] )"
+ }
+ default {
+ send Parser
+ "= ref 0"
+ }
+
+ send Parser
+ " in
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "#define [Export.ident] [number(Export.number)]
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "let [Index.ident] : int ref "
+
+ switch Index.opt_init
+ case [E: `= expr] {
+ send Parser
+ "= ref ( [expr(Index.opt_init.expr)] )"
+ }
+ default {
+ send Parser
+ "= ref 0"
+ }
+
+ send Parser
+ " in
+ }
+ case [case_block]
+ {
+ send Parser
+ "| [expr( Stmt.case_block.expr )] ->
+ "begin
+ "[stmt_list( Stmt.case_block._repeat_stmt )]
+ "end;
+ }
+ case [default_block]
+ {
+ send Parser
+ "| _ ->
+ "[stmt_list( Stmt.default_block._repeat_stmt )]
+ }
+ case [case_label]
+ {
+ send Parser
+ "case [expr( Stmt.case_label.expr )]:
+ }
+ case [AS: assign_stmt]
+ {
+ switch AS.assign_op
+ case [`=]
+ {
+ switch AS.LValue
+ case "stack\[[expr]\]" {
+ send Parser
+ "Array.set stack top.contents [expr(AS.expr)];
+ }
+ case "nfa_bp\[[expr]\].state" {
+ send Parser
+ "Array.set nfa_bp_state nfa_len.contents [expr(AS.expr)];
+ }
+ case "nfa_bp\[[expr]\].p" {
+ send Parser
+ "Array.set nfa_bp_p nfa_len.contents [expr(AS.expr)];
+ }
+ default {
+ send Parser
+ "[lvalue(AS.LValue)] := [expr(AS.expr)];
+ }
+ }
+ case [`+=]
+ {
+ parse RhsAsFactor: expr_factor [$AS.LValue]
+ send Parser
+ "[lvalue(AS.LValue)] := [expr_factor(RhsAsFactor)] + [expr(AS.expr)];
+ }
+ case [`-=]
+ {
+ parse RhsAsFactor: expr_factor [$AS.LValue]
+ send Parser
+ "[lvalue(AS.LValue)] := [expr_factor(RhsAsFactor)] - [expr(AS.expr)];
+ }
+ default {
+ 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<ocaml_out::ocaml_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ MO: ocaml_out::ocaml_out = Parser->finish()
+
+ if MO {
+ send Output
+ [MO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+
+end
+
+void trans( Output: stream, Start: start )
+{
+ ml_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-ruby.lm b/src/cgil/rlhc-ruby.lm
new file mode 100644
index 00000000..87119465
--- /dev/null
+++ b/src/cgil/rlhc-ruby.lm
@@ -0,0 +1,527 @@
+include 'ril.lm'
+
+namespace ruby_out
+ token _IN_ /''/
+ token _EX_ /''/
+
+ lex
+ token comment /
+ '#' any* :> '\n'
+ /
+
+ literal `def `class `begin `end `while `if
+
+ token id
+ /[a-zA-Z_][a-zA-Z_0-9]*/
+
+ token number /
+ [0-9]+
+ /
+
+ token string /
+ '"' ( [^"\\] | '\\' any ) * '"' |
+ "'" ( [^'\\] | '\\' any ) * "'" |
+ "/" ( [^/\\] | '\\' any ) * "/"
+ /
+
+ token symbol /
+ '!' | '#' | '$' | '%' | '&' | '(' | ')' | '*' |
+ '+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' |
+ '=' | '>' | '?' | '@' | '[' | ']' | '^' | '|' |
+ '~' | '{' | '}' | '\\' /
+
+ ignore
+ /[ \t\v\r\n]+/
+ end
+
+ def item
+ [comment]
+ | [id]
+ | [number]
+ | [symbol]
+ | [string]
+ | [`begin _IN_]
+ | [`class _IN_]
+ | [`while _IN_]
+ | [`if _IN_]
+ | [`def _IN_]
+ | [_EX_ `end]
+
+ def ruby_out
+ [_IN_ _EX_ item*]
+end
+
+global Parser: parser<ruby_out::ruby_out>
+
+void tok_list( TL: host::tok* )
+{
+ for Tok: host::tok in repeat(TL) {
+ switch Tok
+ case [host::`${ StmtList: stmt* host::`}$]
+ {
+ send Parser
+ "begin
+ "[stmt_list( StmtList )]
+ "end
+ }
+ case [host::`={ Expr: expr host::`}=]
+ expr( Expr )
+ case [E: escape] {
+ Str: str = $E
+ send Parser
+ "[Str.suffix( 1 )]"
+ }
+ default {
+ send Parser [Tok]
+ }
+ }
+}
+
+void embedded_host( EH: embedded_host )
+{
+ switch EH
+ case [`host `( string `, uint `) `={ TL: host::tok* host::`}=]
+ {
+ send Parser
+ "([tok_list( TL )])"
+ }
+ case [`host `( string `, uint `) `${ TL: host::tok* host::`}$]
+ {
+ send Parser
+ "begin
+ " [tok_list( TL )]
+ "end
+ }
+ 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' '(' ident ',' expr ')']
+ {
+ send Parser
+ [expr( ExprFactor.expr )]
+ }
+ case ['deref' '(' ident ',' expr ')']
+ {
+ send Parser
+ [ ExprFactor.ident '[' expr( ExprFactor.expr ) ']']
+ if $ExprFactor.ident == 'data'
+ send Parser '.ord'
+ }
+ case [T: `TRUE]
+ {
+ T.data = 'true'
+ send Parser [T]
+ }
+ case [F: `FALSE]
+ {
+ F.data = 'false'
+ send Parser [F]
+ }
+ case [N: `nil]
+ {
+ N.data = '0'
+ send Parser [N]
+ }
+ case [Number: number]
+ {
+ ruby_number( Number )
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast Open: `( Type: type Close: `) expr_factor]
+ {
+ #send Parser [Open]
+ #type( Type )
+ #send Parser [Close]
+ expr_factor( ExprFactor._expr_factor )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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 [E1: embedded_host `-> E2: lvalue]
+ {
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' E ']']
+ }
+ 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( ExprTest: expr_test )
+{
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+}
+
+void expr( Expr: expr )
+{
+ expr_test( Expr.expr_test )
+}
+
+void type( Type: type )
+{
+ switch Type
+ case "s8"
+ send Parser ['byte ']
+ case "s16"
+ send Parser ['short ']
+ case "s32"
+ send Parser ['int ']
+ case "s64"
+ send Parser ['long ']
+ case "s128"
+ send Parser ['long long ']
+ case "uint"
+ send Parser ['int ']
+ default
+ send Parser [Type]
+}
+
+void ruby_number( Number: number )
+{
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]"
+ default
+ send Parser [Number]
+}
+
+void ruby_num_list( NumList: num_list )
+{
+ for Number: number in NumList
+ send Parser "[ruby_number( Number )], "
+}
+
+void stmt( Stmt: stmt )
+{
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ send Parser
+ "class << self
+ " attr_accessor :[ A.ident ]
+ " private :[ A.ident ], :[ A.ident ]=
+ "end
+ "self.[ A.ident ] = \[
+ " [ruby_num_list( A.num_list )]
+ "\]
+ "
+ }
+ case [V: static_value] {
+ send Parser
+ "class << self
+ " attr_accessor :[ V.ident ]
+ "end
+ "self.[ 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
+ "elsif ( [expr(ElseIfExpr)] )
+ " [stmt(ElseIfStmt)]
+ }
+
+ if ( match ElseClauseOpt ['else' ElseStmt: stmt] ) {
+ send Parser
+ "else
+ " [stmt(ElseStmt)]
+ }
+ send Parser
+ "end
+ }
+ case ['while' '(' WhileExpr: expr ')' WhileStmt: stmt] {
+ send Parser
+ "while ( [expr(WhileExpr)] )
+ " [stmt(WhileStmt)]
+ "end
+ }
+ case ['switch' '(' SwitchExpr: expr ')' '{' StmtList: stmt* '}'] {
+ send Parser
+ "case [expr(SwitchExpr)]
+ "when -2 then
+ "begin
+ " [stmt_list(StmtList)]
+ "end
+ "end
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr(ExprExpr) Semi]
+ }
+ case [L: `{ TL: stmt* R: `}] {
+ send Parser
+ "begin
+ "[stmt_list(TL)]
+ "end
+ }
+ # [declaration]
+ case [
+ TypeList: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+ else {
+ send Parser
+ "= 0
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "class << self
+ " attr_accessor :[ Export.ident ]
+ "end
+ "self.[ Export.ident ] = [ ruby_number(Export.number) ];
+ "
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "[Index.ident]"
+
+ if match Index.opt_init [E: `= expr] {
+ send Parser
+ [E expr(Index.opt_init.expr)]
+ }
+ else {
+ send Parser
+ "= 0
+ }
+
+ send Parser ";
+ }
+ case [case_block]
+ {
+ send Parser
+ "end
+ "when [expr( Stmt.case_block.expr )] then
+ "begin
+ "[stmt_list( Stmt.case_block._repeat_stmt )]
+ }
+ case [default_block]
+ {
+ send Parser
+ "end
+ "else
+ "begin
+ "[stmt_list( Stmt.default_block._repeat_stmt )]
+ }
+ case [goto_label] {}
+ case [goto_stmt] {}
+ case [AS: assign_stmt]
+ {
+ send Parser
+ "[lvalue(AS.LValue) AS.assign_op expr(AS.expr)];
+ }
+ case [continue_stmt]
+ {
+ send Parser
+ "next;
+ }
+ default {
+ # catches unspecified cases
+ send Parser [Stmt]
+ }
+}
+
+void stmt_list( StmtList: stmt* )
+{
+ for Stmt: stmt in repeat( StmtList )
+ stmt( Stmt )
+}
+
+void ruby_trans( Output: stream, Start: start )
+{
+ Parser = new parser<ruby_out::ruby_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ RO: ruby_out::ruby_out = Parser->finish()
+
+ if RO {
+ send Output
+ [RO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+}
+
+void trans( Output: stream, Start: start )
+{
+ ruby_trans( Output, Start )
+}
+
+include 'rlhc-main.lm'
diff --git a/src/cgil/rlhc-rust.lm b/src/cgil/rlhc-rust.lm
new file mode 100644
index 00000000..03f8b688
--- /dev/null
+++ b/src/cgil/rlhc-rust.lm
@@ -0,0 +1,534 @@
+include 'ril.lm'
+
+namespace rust_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 lifetime / "'" id /
+
+ token string /
+ '"' ( [^"\\] | '\\' any ) * '"' |
+ "'" ( [^'\\] | '\\' any ) "'"
+ /
+
+ ignore
+ /[ \t\v\r\n]+/
+ end
+
+ def item
+ [comment]
+ | [id]
+ | [number]
+ | [symbol]
+ | [string]
+ | [lifetime]
+ | [`{ _IN_ item* _EX_ `} ]
+
+ def rust_out
+ [_IN_ _EX_ item*]
+end
+
+namespace rust_gen
+
+ global Parser: parser<rust_out::rust_out>
+
+ 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 [I: ident `[ E: expr `]]
+ {
+ send Parser
+ "[I]\[([expr( E )]) as usize\]"
+ }
+ case ['offset' '(' ident ',' expr ')']
+ {
+ send Parser
+ "( [expr( ExprFactor.expr )] ) as i32"
+ }
+ case ['deref' '(' I: ident ',' E: expr ')']
+ {
+ send Parser
+ "[I]\[([expr( E )]) as usize\]
+ }
+ case [T: `TRUE]
+ {
+ T.data = 'true'
+ send Parser [T]
+ }
+ case [F: `FALSE]
+ {
+ F.data = 'false'
+ send Parser [F]
+ }
+ case [N: `nil]
+ {
+ N.data = '0'
+ send Parser [N]
+ }
+ case [Number: number]
+ {
+ number( Number )
+ }
+ case [E1: embedded_host `-> E2: expr_factor]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ expr_factor( E2 )
+ }
+ case [`cast `( T: type `) E: expr_factor]
+ {
+ send Parser
+ "( [expr_factor( E )] ) as [type(T)]"
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' expr(E) ' as usize]']
+ }
+ default {
+ # Catches cases not specified
+ send Parser [ExprFactor]
+ }
+ }
+
+ void lvalue( ExprFactor: lvalue )
+ {
+ switch ExprFactor
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [I: ident O: `[ E: expr C: `]]
+ {
+ send Parser
+ "[I]\[([expr( E )]) as usize\]
+ }
+ case [E1: embedded_host `-> E2: lvalue]
+ {
+ # The accessor operator is contained wihtin the lhs.
+ embedded_host( E1 )
+ lvalue( E2 )
+ }
+ case [I: ident `[ E: expr `] `. F: ident] {
+ send Parser
+ [^I '_' ^F '[' expr(E) ' as usize]']
+ }
+ 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 [`~ EFO: expr_factor_op]
+ {
+ send Parser
+ "![expr_factor_op( EFO )]
+ }
+ 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( ExprTest: expr_test )
+ {
+ switch ExprTest
+ case [expr_test Op: test_op expr_shift]
+ {
+ expr_test( ExprTest._expr_test )
+ send Parser [Op]
+ expr_shift( ExprTest.expr_shift )
+ }
+ case [expr_shift]
+ {
+ expr_shift( ExprTest.expr_shift )
+ }
+ }
+
+ void expr( Expr: expr )
+ {
+ expr_test( Expr.expr_test )
+ }
+
+ void type( Type: type )
+ {
+ switch Type
+ case "s8"
+ send Parser ['i8 ']
+ case "s16"
+ send Parser ['i16 ']
+ case "s32"
+ send Parser ['i32 ']
+ case "s64"
+ send Parser ['i64 ']
+ case "s128"
+ send Parser ['i128']
+ case "int"
+ send Parser ['i32']
+ case "uint"
+ send Parser ['u32']
+ default
+ send Parser [Type]
+ }
+
+ void number( Number: number )
+ {
+ switch Number
+ case [`u `( uint `) ]
+ send Parser "[Number.uint]"
+ default
+ send Parser [Number]
+ }
+
+ void num_list( NumList: num_list )
+ {
+ for Number: number in NumList
+ send Parser "[number( Number )], "
+ send Parser "0"
+ }
+
+ void stmt( Stmt: stmt )
+ {
+ switch Stmt
+ case [EH: embedded_host]
+ {
+ send Parser
+ [embedded_host( EH )]
+ }
+ case [A: static_array] {
+ Length: int = 1
+ for Number: number in A.num_list
+ Length = Length + 1
+
+ send Parser
+ "static [A.ident]: \[[type(A.type)]; [Length]\] = \[ [num_list(A.num_list)] \];
+ }
+ case [V: static_value] {
+ send Parser
+ "static [V.ident]: i32 = [V.number];
+ }
+ case [D: declaration] {
+ send Parser
+ "let mut [D.ident] "
+
+ switch D.opt_init
+ case [E: `= expr] {
+ send Parser
+ "= [expr(D.opt_init.expr)];
+ }
+ default {
+ send Parser
+ "= 0;
+ }
+ }
+ case [Index: index_stmt]
+ {
+ send Parser
+ "let mut [Index.ident] :i32"
+
+ switch Index.opt_init
+ case [E: `= expr] {
+ send Parser
+ "= [expr(Index.opt_init.expr)];
+ }
+ default {
+ send Parser
+ "= 0;
+ }
+ }
+ case [
+ 'if' `( IfExpr: expr `) 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 [`continue CL: ident `;] {
+ send Parser
+ "continue '[CL];
+ }
+ case [`break BL: ident `;] {
+ send Parser
+ "break '[BL];
+ }
+ case [BL: break_label? 'while' '(' WhileExpr: expr ')' '{' StmtList: stmt* '}' ] {
+ if match BL [bl: break_label]
+ send Parser "'[bl.ident]: "
+
+ send Parser
+ "while ( [expr(WhileExpr)] ) {
+ " [stmt_list(StmtList)]
+ "}
+ }
+ case [`switch `( SwitchExpr: expr `) `{ StmtList: stmt* `}] {
+ send Parser
+ "match ( [expr(SwitchExpr)] ) {
+ " [stmt_list(StmtList)]
+
+ NeedDef: bool = true
+ for Stmt: stmt in repeat(StmtList) {
+ if match Stmt [default_block]
+ NeedDef = false
+ }
+
+ if NeedDef {
+ send Parser
+ " _ => {}
+ }
+
+ send Parser
+ "}
+ }
+ case [ExprExpr: expr Semi: `;] {
+ send Parser
+ [expr(ExprExpr) Semi]
+ }
+ case [L: `{ TL: stmt* R: `}] {
+ send Parser
+ [L stmt_list(TL) R]
+ }
+ case [
+ TypeList: opt_const Type: type
+ Ident: ident OptInit: opt_init Semi: `;
+ ]
+ {
+ send Parser
+ [TypeList type(Type) Ident]
+
+ if match OptInit [E: `= expr] {
+ send Parser
+ [E expr(OptInit.expr)]
+ }
+
+ send Parser
+ [Semi]
+ }
+ case [Export: export_stmt]
+ {
+ send Parser
+ "#define [Export.ident] [number(Export.number)]
+ }
+ case ['fallthrough' ';']
+ {
+ # Nothing needed here.
+ }
+ case [case_block]
+ {
+ send Parser
+ "[expr( Stmt.case_block.expr )] => {
+ "[stmt_list( Stmt.case_block._repeat_stmt )]
+ "}
+ }
+ case [default_block]
+ {
+ send Parser
+ "_ => {
+ "[stmt_list( Stmt.default_block._repeat_stmt )]
+ "}
+ }
+ case [case_label]
+ {
+ send Parser
+ "case [expr( Stmt.case_label.expr )]:
+ }
+ 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<rust_out::rust_out>()
+
+ if ( Start.opt_bom.bom )
+ send Output [Start.opt_bom.bom]
+
+ stmt_list( Start._repeat_stmt )
+
+ CO: rust_out::rust_out = Parser->finish()
+
+ if CO {
+ send Output
+ [CO]
+ }
+ else {
+ send stderr
+ "failed to parse output: [Parser->error]
+ }
+ }
+end
+
+void trans( Output: stream, Start: start )
+{
+ rust_gen::trans( Output, Start )
+}
+
+include 'rlhc-main.lm'