function extract(l, a) { var r = []; for(var i = 0; i < l.length; i++) { r.push(l[i][a]); } return r; } function keys(o) { var r = []; for(var k in o) { r.push(k); } return r; } function unique(l) { var o = {}; for(var i = 0; i < l.length; i++) { o[l[i]] = true; } return keys(o); } function A(n) { var r = new Array(n); for(var a = 1; a <= n; ++a) { r.push(arguments[a]); } return r; } function S(s) { return s; } function concat(n) { var r = arguments[1]; for(var a = 2; a <= n; a++) { if(typeof r == "string") { r = r + arguments[a]; } else { r = r.concat(arguments[a]); } } return r; } function join(l, s) { var r = l[0]; for(var i = 1; i < l.length; i++) { r = r + s + l[i]; } return r; } function stringify(s) { return s.toProgramString(); } /* ometa Example { _c :x = ^char:c ?(x == c) -> c, trigraph = _c("?") _c("?") ( _c("=") -> "#" | _c("(") -> "[" | _c("/") -> "\\" | _c(")") -> "]" | _c("'") -> "^" | _c("<") -> "{" | _c("!") -> "|" | _c(">") -> "}" | _c("-") -> "~" ):c -> c, char = ((_c("\\") | _c("?") _c("?") _c("/")) new_line)* ( trigraph | ^char ):c -> c, } ==== struct Example_data { struct OMeta_data *parent; }; obj Example__c(struct Example_data *_o, jmp_buf _f, obj x) { obj c; c = OMeta_char(_o, _f); if(x == c) { longjmp(_f, 1); } return c; } obj Example_trigraph(struct Example_data *_o, jmp_buf _f) { obj c; Example__c(_o, _f, "?"); Example__c(_o, _f, "?"); { int _i0 = _o->parent->input.index; jmp_buf _f0; int _s0 = 0; setjmp(_f0); _o->parent->input.index = _i0; switch(_s0++) { case 0: Example__c(_o, _f0, "="); c = "#"; break; case 1: Example__c(_o, _f0, "("); c = "["; break; case 2: Example__c(_o, _f0, "/"); c = "\\"; break; case 3: Example__c(_o, _f0, ")"); c = "]"; break; case 4: Example__c(_o, _f0, "'"); c = "^"; break; case 5: Example__c(_o, _f0, "<"); c = "{"; break; case 6: Example__c(_o, _f0, "!"); c = "|"; break; case 7: Example__c(_o, _f0, ">"); c = "}"; break; case 8: Example__c(_o, _f0, "-"); c = "~"; break; case 9: longjmp(_f, 1); } } return c; } // char = ((_c("\\") | _c("?") _c("?") _c("/")) new_line)* ( trigraph | ^char ):c -> c, obj Example_char(struct Example_data *_o, jmp_buf _f) { obj c; { jmp_buf _f0; int _s0 = 0, _i0 = _o->parent->input.index; _s0 = setjmp(_f0); _o->parent->input.index = _i0; while(!_s0) { _i0 = _o->parent->input.index; { int _i1 = _o->parent->input.index; jmp_buf _f1; int _s1 = 0; setjmp(_f1); _o->parent->input.index = _i1; switch(_s1++) { case 0: Example__c(_o, _f1, "\\"); break; case 1: Example__c(_o, _f1, "?"); Example__c(_o, _f1, "?"); Example__c(_o, _f1, "/"); break; case 2: longjmp(_f1, 1); } } Example_new_line(_o, _f0); } } { int _i0 = _o->parent->input.index; jmp_buf _f0; int _s0 = 0; setjmp(_f0); _o->parent->input.index = _i0; switch(_s0++) { case 0: c = Example_trigraph(_o, _f0); break; case 1: c = OMeta_char(_o, _f0); break; case 2: longjmp(_f, 1); } } return c; } struct Example { struct OMeta *parent; struct spec_fun *funs; }; */ ometa OMetaCTranslator { App 'super' anything+:args -> ['omApply(__o->spec->parent, "',args[0],'", __o, __f', args.length > 1 ? ', ' : '', args.slice(1).join(', '), ', NULL)'].join(''), App 'foreign' :grm anything+:args -> ['omApply(', grm, ', "',args[0],'", __o, __f', args.length > 1 ? ', ' : '', args.slice(1).join(', '), ', NULL)'].join(''), App :rule anything+:args -> ['omApply(__o->spec, "',rule,'", __o, __f, ', args.join(', '), ', NULL)'].join(''), App :rule -> ['omApply(__o->spec, "',rule,'", __o, __f, NULL)'].join(''), Act :expr -> expr, Pred :expr -> ['omApply(__o->spec, "_pred", __o, __f, I(', expr, '), NULL)'].join(''), Or transFn*:xs -> ['omApply(__o->spec, "_or", __o, __f, ', xs.join(', '), ', NULL)'].join(''), XOr transFn*:xs {xs.unshift((this.name + "." + this.rName).toProgramString())} -> ['omApply(__o->spec, "_xor", __o, __f, ', xs.join(','), ', NULL)'].join(''), And notLast(#trans)*:xs trans:y {xs.push('return ' + y)} -> ['CB( ', xs.join(';'), ')(__o, __f)'].join(''), And -> ';', Opt transFn:x -> ['OMeta__opt(__o, __f, ', x, ')'].join(''), Many transFn:x -> ['OMeta__many(__o, __f, ', x, ')'].join(''), Many1 transFn:x -> ['OMeta__many1(__o, __f, ', x, ')'].join(''), Set :n trans:v -> [n, ' = ', v].join(''), Not transFn:x -> ['OMeta__not(__o, __f, ', x, ')'].join(''), Lookahead transFn:x -> ['OMeta__lookahead(__o, __f, ', x, ')'].join(''), Form transFn:x -> ['OMeta__form(__o, __f, ', x, ')'].join(''), ConsBy transFn:x -> ['OMeta__consumedBy(__o, __f, ', x, ')'].join(''), IdxConsBy transFn:x -> ['OMeta__idxConsumedBy(__o, __f, ', x, ')'].join(''), JumpTable jtCase*:cases -> this.jumpTableCode(cases), Interleave intPart*:xs -> ['OMeta__interleave(__o, __f, ', xs.join(','), ')'].join(''), Rule :name {this.rName = name} locals:ls trans:body -> ["{\"" + name + "\", &" + this.name + "_" + name + "}", ['obj ', this.name, '_', name, '(struct ometa *__o, jmp_buf __f) {\n\t', ls, 'return ', body, ';\n}'].join('')], Grammar :name :sName {this.name = name} {this.sName = sName} trans*:rules -> [extract(rules, 1).join("\n\n"), '\n\nstatic struct ometa_spec_fun ', name, '_funs[] = {\n\t', extract(rules, 0).join(",\n\t") ,',\n\t{NULL, NULL}\n};\n\nstruct ometa_spec ', name, ' = {&', sName, ', ', name, '_funs};'].join(''), intPart = [:mode transFn:part] -> (mode.toProgramString() + "," + part), jtCase = [:x trans:e] -> [x.toProgramString(), e], locals = [string+:ss] -> ['obj ', unique(ss).join(', '), ';\n\t'].join('') | [] -> '', trans = [:t apply(t):ans] -> ans, transFn = trans:x -> ['CB( ', x, '; )\n'] .join('') } OMetaCTranslator.jumpTableCode = function(cases) { var buf = []; buf.push("CB(obj __x = OMeta_anything(o->spec, S(\"anything\"), __o, __f);\n\t") for(var i = 0; i < cases.length; i += 1) buf.push("if(equality(" + cases[i][0] + ", __x)) { return " + cases[i][1] + "; }\n\t") buf.push("longjmp(__f, 1); )(__o, __f)") return buf.join(""); } // Lets remove some JS injection caused the original parser does // Also, lets split set from match argument to rule argument ometa OMetaCParser <: BSOMetaParser { application = "^" name:rule args:as -> [#App, "super", rule].concat(as) | name:grm "." name:rule args:as -> [#App, "foreign", grm, rule].concat(as) | name:rule args:as -> [#App, rule].concat(as), optBind :x = ':' name:n -> { this.locals.push(n); [#Set, n, x] } | empty -> x, expr3 = ":" name:n -> { this.locals.push(n); [#Set, n, [#App, #anything]] } | (expr2:x optIter(x) | semAction):e optBind(e) | semPred, rule = &(ruleName:n) !(this.locals = []) rulePart(n):x ("," rulePart(n))*:xs -> [#Rule, n, this.locals, [#Or, x].concat(xs)] } function MyTranslateCode(s) { var translationError = function(m, i) { throw fail }; var tree = OMetaCParser.matchAll(s, "grammar", undefined, function(m, i) { throw objectThatDelegatesTo(fail, {errorPos: i}) }) return OMetaCTranslator.match(tree, "trans", undefined, translationError) } MyTranslateCode("""ometa CToken { _c :x = ^char:c ?(x == c) -> c, trigraph = _c("?") _c("?") ( _c("=") -> "#" | _c("(") -> "[" | _c("/") -> "\\" | _c(")") -> "]" | _c("'") -> "^" | _c("<") -> "{" | _c("!") -> "|" | _c(">") -> "}" | _c("-") -> "~" ):c -> c, new_line = ( _c("\r") _c("\n") | _c("\r") | _c("\n") ) -> "\n", char = ((_c("\\") | _c("?") _c("?") _c("/")) new_line)* ( trigraph | ^char ):c -> c, token = spaces ( keyword | identifier | constant | string_literal | punctuator ), preprocessing_token = ( spaces | header_name | identifier | pp_number | character_constant | string_literal | punctuator ), space = ^space | ( fromTo("//", "\n") | fromTo("/*", "*/") ) -> "\n", spaces = space*:s -> join(s, ""), keyword = ( "auto" | "if" | "unsigned" | "break" | "inline" | "void" | "case" | "int" | "volatile" | "char" | "long" | "while" | "const" | "register" | "_Alignas" | "continue" | "restrict" | "_Alignof" | "default" | "return" | "_Atomic" | "do" | "short" | "_Bool" | "double" | "signed" | "_Complex" | "else" | "sizeof" | "_Generic" | "enum" | "static" | "_Imaginary" | "extern" | "struct" | "_Noreturn" | "float" | "switch" | "_Static_assert" | "for" | "typedef" | "_Thread_local" | "goto" | "union" ) ~( nondigit | digit ), identifier = identifier_nondigit:first ( identifier_nondigit | digit )*:rest -> join(concat(2, [first], rest), ""), identifier_nondigit = nondigit | universal_character_name, nondigit = '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z', digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9', universal_character_name = '\\' 'u' hex_quad | '\\' 'U' hex_quad hex_quad, hex_quad = hexadecimal_digit hexadecimal_digit hexadecimal_digit hexadecimal_digit, constant = integer_constant | floating_constant | enumeration_constant | character_constant, integer_contant = ( decimal_constant | octal_constant | hexadecimal_constant ) integer_suffix?, decimal_constant = nonzero_digit digit*, octal_constant = '0' octal_digit*, hexadecimal_constant = hexadecimal_prefix hexadecimal_digit hexadecimal_digit*, hexadecimal_prefix = '0' | ( 'x' | 'X' ), nonzero_digit = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9', octal_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7', hexadecimal_digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F', integer_suffix = unsigned_suffix long_suffix? | unsigned_suffix long_long_suffix | long_suffix unsigned_suffix? | long_long_suffix unsigned_suffix?, unsigned_suffix = 'u' | 'U', long_suffix = 'l' | 'L', long_long_suffix = 'll' | 'LL', floating_constant = decimal_floating_constant | hexadecimal_floating_constant, decimal_floating_constant = fractional_consant exponent_part? floating_suffix? | digit_sequence exponent_part floating_suffix?, hexadecimal_floating_constant = hexadecimal_prefix ( hexadecimal_fractional_constant | hexadecimal_digit+ ) binary_exponent_part floating_suffix?, fractional_constant = digit* '.' digit+ | digit+ '.', exponent_part = ( 'e' | 'E' ) sign? digit+, sign = ( '+' | '-' ), hexadecimal_fractional_constant = hexadecimal_digit* '.' hexadecimal_digit* | hexadecimal_digit+, binary_exponent_part = ( 'P' | 'p' ) sign? digit+, floating_suffix = 'f' | 'l' | 'F' | 'L', enumeration_constant = identifier, c_char = ~'\'' ~'\\' ~'\n' char:c -> c | escape_sequence, escape_sequence = simple_escape_sequence | octal_escape_sequence | hexadecimal_escape_sequence | universal_character_name, simple_escape_sequence = '\\' ( '\'' | '"' | '?' | '\\' | 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' ), octal_escape_sequence = '\\' ( octal_digit octal_digit octal_digit | octal_digit octal_digit | octal_digit ), hexadecimal_escape_sequence = '\\' 'x' hexadecimal_digit+, string_literal encoding_prefix? '"' s_char* '"', encoding_prefix = 'u' '8' | 'u' | 'U' | 'L', s_char = ~'"' ~'\\' ~'\n' char:c -> c | escape_sequence, punctuator = '[' | ']' | '(' | ')' | '{' | '}' | '?' | ';' | '~' | ',' | '-''>' | '-''=' | '-''-' | '-' | '+''+' | '+''=' | '+' | '&''&' | '&''=' | '&' | '*''=' | '*' | '!''=' | '!' | '/''=' | '/' | '%''=' | '%''>' | '%'':''%'':' | '%'':' '%' | '<'':' | '<''=' | '<''%' | '<''<''=' | '<''<' | '<' | '>''>''=' | '>''>' | '>''=' | '>' | '=''=' | '=' | '^''=' | '^' | '|''=' | '|''|' | '|' | ':''>' | ':' | '.''.''.' | '.' | '#''#' | '#', header_name = '<' h_char+:h '>' -> concat(3, "<", join(h, ""), ">") | '"' q_char+:h '"' -> concat(3, "\"", join(h, ""), "\""), h_char = ~'\n' ~'>' char:c -> c, q_char = ~'\n' ~'"' char:c -> c, pp_number = ( digit | '.' digit ):first ( digit | 'e' sign | 'E' sign | 'p' sign | 'P' sign | identifier_nondigit | '.' )*:rest -> join(concat(2, [first], rest), "") }""")