summaryrefslogtreecommitdiff
path: root/cgil/rlhc-go.lm
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2020-03-14 13:36:41 +0200
committerAdrian Thurston <thurston@colm.net>2020-03-14 13:36:41 +0200
commit569d9766e632ec830a70eb9f6c9b69297b63719f (patch)
tree90c71f84a871367f7996c4fc31d2207507e869a5 /cgil/rlhc-go.lm
parent4ebe2c5f8adb33ae1525197012e790e01f5ea341 (diff)
downloadcolm-569d9766e632ec830a70eb9f6c9b69297b63719f.tar.gz
moved rlhc (now calling it cgil) to it's own place
cgil: Code Gen Intermediate Language
Diffstat (limited to 'cgil/rlhc-go.lm')
-rw-r--r--cgil/rlhc-go.lm453
1 files changed, 453 insertions, 0 deletions
diff --git a/cgil/rlhc-go.lm b/cgil/rlhc-go.lm
new file mode 100644
index 00000000..21aa1cee
--- /dev/null
+++ b/cgil/rlhc-go.lm
@@ -0,0 +1,453 @@
+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'