{"id":23239423,"url":"https://github.com/r32/lex","last_synced_at":"2026-04-02T02:37:05.913Z","repository":{"id":65275419,"uuid":"145311525","full_name":"R32/lex","owner":"R32","description":"Build lexer and simple parser(SimpleLR) in macro, It also provides lexer and simpleLR tool for c language","archived":false,"fork":false,"pushed_at":"2023-08-29T06:46:24.000Z","size":608,"stargazers_count":19,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-03T01:34:50.272Z","etag":null,"topics":["lexer","parser","slr-parser"],"latest_commit_sha":null,"homepage":"","language":"Haxe","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/R32.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-19T14:44:15.000Z","updated_at":"2023-03-11T07:41:11.000Z","dependencies_parsed_at":"2024-12-19T04:32:50.967Z","dependency_job_id":"f6adee68-0a0d-4994-842e-d6ade18f0844","html_url":"https://github.com/R32/lex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/R32/lex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/R32%2Flex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/R32%2Flex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/R32%2Flex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/R32%2Flex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/R32","download_url":"https://codeload.github.com/R32/lex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/R32%2Flex/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266764531,"owners_count":23980580,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lexer","parser","slr-parser"],"created_at":"2024-12-19T04:28:08.914Z","updated_at":"2026-04-02T02:37:05.887Z","avatar_url":"https://github.com/R32.png","language":"Haxe","funding_links":[],"categories":[],"sub_categories":[],"readme":"Lex\r\n------\r\n\r\nBuild lexer and simple parser(SimpleLR) in macro.\r\n\r\nLIMITS:\r\n\r\n1. In haxe, You can't use it in [`macro-in-macro`](https://github.com/HaxeFoundation/haxe/pull/7496)\r\n\r\n2. Suitable for ASCII only.\r\n\r\n## Samples\r\n\r\n* [SLR tool for c langauge](/tools/generator/CSLR.hx)\r\n\r\n  \u003e `haxelib run lex --slr TPL.slr TPL.lex`\r\n\r\n  basic demo : [test.slr](/tools/test/test.slr) ==\u003e [`test_slr.c`](/tools/test/test_slr.c)\r\n\r\n  json parser demo : [rjson_parser.slr](https://github.com/R32/clib/blob/master/src/haxe/rjson/rjson_parser.slr#L66) ==\u003e [`rjson_parser_slr.c`](https://github.com/R32/clib/blob/master/src/rjson_parser_slr.c)\r\n\r\n* [Lexer tool for c langauge](/tools/generator/CLexer.hx)\r\n\r\n  \u003e run `haxelib run lex TPL.lex` basic demo : [test.lex](/tools/test/test.lex) ==\u003e [`test_lex.c`](/tools/test/test_lex.c)\r\n\r\n* [hello world](#Usage)\r\n\r\n* [hscript parser](/demo/)\r\n\r\n## Status\r\n\r\n* Lexer\r\n\r\n  ```haxe\r\n  static function main()  {\r\n      var str = lms.ByteData.ofString('exec(123 + 456)');\r\n      var lex = new Lexer(str);\r\n      var t = lex.token();\r\n      while (t != Eof) {\r\n          trace(s_token(t));\r\n          t = lex.token();\r\n      }\r\n  }\r\n\r\n  enum Op {\r\n      Add;\r\n      Sub;\r\n      Mul;\r\n      Div;\r\n  }\r\n\r\n  enum Token {\r\n      Eof;\r\n      LParen;\r\n      RParen;\r\n      Op( op : Op );\r\n      CIdent( id : String);\r\n      CInt( i : Int);\r\n      CString( s : String);\r\n  }\r\n\r\n  /*\r\n   * The following meta characters are supported in string:\r\n   * `*`: zero or more\r\n   * `+`: one or more\r\n   * `?`: zero or one\r\n   * `[`: begin char range\r\n   * `]`: end char range\r\n   * `\\`: escape next char\r\n   * `|`: or\r\n   *\r\n   * The newly added syntax:\r\n   *\r\n   * \"a\" | \"b\"    =\u003e /a|b/\r\n   * \"a\" + \"b\"    =\u003e /ab/  \"+\" has a higher priority than \"|\"\r\n   * Opt(\"abc\")   =\u003e /(abc)?/\r\n   * Star(\"abc\")  =\u003e /(abc)*\r\n   * Plus(\"abc\")  =\u003e /(abc)+/\r\n   *\r\n   * For example:\r\n   * var integer    = \"0\" | \"[1-9][0-9]*\";\r\n   * var floatpoint = \".[0-9]+\" | \"[0-9]+.[0-9]*\";\r\n   * var exp        = \"[eE][+-]?[0-9]+\";\r\n   * var float      = integer + Opt(exp) | floatpoint + Opt(exp);\r\n   *\r\n   */\r\n  @:rule(Eof) class Lexer implements lm.Lexer\u003cToken\u003e {\r\n\r\n      // You could add \"@:skip\" to avoid being parsed into a pattern\r\n\r\n      var r_int = \"0\" | \"-?[1-9][0-9]*\";\r\n\r\n      var r_ident = \"[a-zA-Z_][a-zA-Z_0-9]+\";\r\n\r\n      // Matching 1, The first one will be automatically renamed as \"token\"\r\n      var tok =  [\r\n          \"[ \\t]+\" =\u003e this.token(),   // Recursive Matching 1\r\n          \"+\" =\u003e Op(Add),\r\n          \"-\" =\u003e Op(Sub),\r\n          \"*\" =\u003e Op(Mul),\r\n          \"/\" =\u003e Op(Div),\r\n          \"(\" =\u003e LParen,\r\n          \")\" =\u003e RParen,\r\n          r_int =\u003e\r\n              CInt(Std.parseInt(this.current)),\r\n          r_ident =\u003e\r\n              CIdent(this.current),\r\n          '\"' =\u003e {\r\n              var i = this.pmax;      // save start position\r\n              var t = this.string();  // goto Matching 2\r\n              if (t == Eof)\r\n                  throw \"UnClosed \\\"\";\r\n              this.pmin = i;          // restore pmin\r\n              CString(this.current);\r\n          },\r\n          \"//[^\\n]*\" =\u003e\r\n              this.token(),           // Recursive Matching 1\r\n          _ =\u003e {\r\n              // if error, \"this.pmin \u003e= this.pmax\"\r\n              throw \"UnExpected : \" + this.getString(pmax, pmin - pmax);\r\n          }\r\n      ];\r\n\r\n      // Matching 2\r\n      var string = [\r\n          '\"'     =\u003e CString(\"\"),\r\n          '[^\"]+' =\u003e this.string()    // Recursive Matching 2\r\n      ];\r\n\r\n      // Matching N...\r\n  }\r\n  ```\r\n\r\n* Parser: Only SimpleLR is available.\r\n\r\n  Unlike normal LR parsers, there is no *action-table* - all are *jump-table*.\r\n\r\n  Some conflicts may be resolved in normal *LALR/LR1*, But here conflict errors will be thrown directly.\r\n\r\n  - **Position**: In actions, use `T1`...`TN` to access token positions(instance of `lm.Stream.Tok`)\r\n\r\n    ```hx\r\n    T1.pmax - T1.pmin;\r\n    ```\r\n\r\n    In actions, vairalbe `stream` is instance of `lm.Stream`\r\n\r\n    ```hx\r\n    var tok = stream.peek(0);\r\n    if (tok.term == SomeToken)\r\n        stream.junk(1);\r\n    ```\r\n\r\n  - Combine multiple Tokens:\r\n\r\n    ```haxe\r\n    // 1. uses \"[]\", NOTE: if you put tokens with **different precedence**, a conflict error will be thrown.\r\n    switch(s) {\r\n    case [e1=expr, op = [OpAdd, OpSub], e2=expr]: op == OpAdd ? e1 + e2 : e1 - e2;\r\n    }\r\n\r\n    // 2. uses production(switch), NOTE: This will ignore all token **precedence** from predefine.\r\n    // But you can use \"@:prec(XXX)\" to enforce the **precedence** for it\r\n    case [e1=expr, op = op, e2=expr]: trace(op == OpAdd) ... //\r\n\r\n    var op : Token = switch(s) {\r\n    case [OpAdd] : OpAdd;\r\n    case [OpSub] : OpSub;\r\n    case [OpDiv] : OpDiv;\r\n    case [OpMul] : OpMul;\r\n    }\r\n    ```\r\n\r\n  - You can use string literals instead of simple terminators in *stream match*.\r\n\r\n    ```haxe\r\n    switch(s) {\r\n    case [e1=expr, op = [\"+\", \"-\"], e2=expr]: op == OpPlus ? e1 + e2 : e1 - e2;\r\n    case [\"(\", e = expr, \")\"]: e;\r\n    }\r\n    ```\r\n\r\n  - **Operator Precedence**:\r\n\r\n    ```haxe\r\n    // the operator precedence definitions:\r\n    @:rule({\r\n        left: [\"+\", \"-\"],         // The parser could auto reflect(str) =\u003e Token\r\n        left: [OpTimes, OpDiv],   // The lower have higher Priority.\r\n        nonassoc: [UMINUS],       // All characters of the placeholder must be UPPERCASE\r\n    }) class MyParser implements lm.SLR\u003cMyLexer\u003e {\r\n    ```\r\n\r\n\u003cpre\u003e\u003cdetails\u003e\r\n    \u003csummary\u003edetails...\u003c/summary\u003e\u003cp\u003e\r\n    ```\r\n    // UPPERCASE == \"non-terml\", LOWERCASE == \"terml\"\r\n    [..., op, E]: if defined(op)     then case.left.value = E.value\r\n    [..., op, E]: if not defined(op) then case.left = null\r\n    [..., T, E] | [E] | [..., t]:    then case.left = null\r\n    [E, op, ...]: if defined(op)     then case.right.value = E.value\r\n    [E, op, ...]: if not defined(op) then case.right.prio = -1\r\n    [E, T, ...]                      then case.right.prio = -1\r\n    [t, ...]                         then case.right = null\r\n    ```\r\n\u003c/p\u003e\u003c/details\u003e\u003c/pre\u003e\r\n\r\n\r\n### CHANGES\r\n\r\n* `1.0.0`\r\n\r\n* `0.13.0`:\r\n\r\n  - `tool` : Added simple LR tool for c langauge\r\n\r\n  - `slr` : Refactored LR0 code to SLR\r\n\r\n  - `lexer` : Added new syntax Opt(), Star(), Plus() for group.\r\n\r\n### Defines\r\n\r\n* `-D lex_slrtable`: for debug. it will generate a SimpleLR table save as `slr-table.txt`. for example:\r\n\r\n  \u003e You may have to modify the `mmap` field in `debug.Print`\r\n\r\n  ```\r\n  Production:\r\n    (R0)  MAIN --\u003e EXPR $\r\n    (R1)  EXPR --\u003e EXPR [+ -] EXPR\r\n    (R2)       --\u003e EXPR * EXPR\r\n    (R3)       --\u003e EXPR / EXPR\r\n    (R4)       --\u003e ( EXPR )\r\n    (R5)       --\u003e - EXPR\r\n    (R6)       --\u003e int\r\n  -----------------------------------------------------------------------------------------\r\n  |  (S)  | (EP)  |   $   |  int  |   +   |   -   |   *   |   /   |   (   |   )   | EXPR  |\r\n  ----------------------------------------------------------------------------------------- MAIN\r\n  |   0   | NULL  |       |  14   |       |   1   |       |       |   2   |       |   8   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   1   | NULL  |       |  14   |       |   1   |       |       |   2   |       |  10   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   2   | NULL  |       |  14   |       |   1   |       |       |   2   |       |   3   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   3   | NULL  |       |       |   4   |   4   |   6   |   7   |       |  11   |       |\r\n  -----------------------------------------------------------------------------------------\r\n  |   4   | NULL  |       |  14   |       |   1   |       |       |   2   |       |   5   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   5   |  R1   |       |       |       |       |   6   |   7   |       |       |       |\r\n  -----------------------------------------------------------------------------------------\r\n  |   6   | NULL  |       |  14   |       |   1   |       |       |   2   |       |  13   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   7   | NULL  |       |  14   |       |   1   |       |       |   2   |       |  12   |\r\n  -----------------------------------------------------------------------------------------\r\n  |   8   | NULL  |   9   |       |   4   |   4   |   6   |   7   |       |       |       |\r\n  -----------------------------------------------------------------------------------------\r\n  -----------------\r\n  |   9   |  R0   |\r\n  -----------------\r\n  |  10   |  R5   |\r\n  -----------------\r\n  |  11   |  R4   |\r\n  -----------------\r\n  |  12   |  R3   |\r\n  -----------------\r\n  |  13   |  R2   |\r\n  -----------------\r\n  |  14   |  R6   |\r\n  -----------------\r\n  ```\r\n\r\n## Usage\r\n\r\ncopy from [test/subs/Demo.hx](test/subs/Demo.hx)\r\n\r\n```hx\r\n@:analyzer(no_optimize)\r\nclass Demo {\r\n    static function main() {\r\n        var str = '1 - 2 * (3 + 4) + 5 * Unexpected 6';\r\n        var lex = new Lexer(lms.ByteData.ofString(str));\r\n        var par = new Parser(lex);\r\n        trace(par.main() == (1 - 2 * (3 + 4) + 5 * 6));\r\n    }\r\n}\r\n\r\n// The lm.LR0 Parser only works with \"enum abstract (Int) to Int\"\r\nenum abstract Token(Int) to Int {\r\n    var Eof = 0;\r\n    var CInt;\r\n    var OpPlus;\r\n    var OpMinus;\r\n    var OpTimes;\r\n    var OpDiv;\r\n    var LParen;\r\n    var RParen;\r\n    var CIdent;\r\n}\r\n\r\n/*\r\n * @:rule(EOF, cmax = 255) See the example below:\r\n *   Eof is a custom terminator which is defined in \"\u003cToken\u003e\" (required)\r\n *   127 is the custom maximum char value. (optional, default is 255)\r\n */\r\n@:rule(Eof, 127) class Lexer implements lm.Lexer\u003cToken\u003e {\r\n    var inter = \"0|[1-9][0-9]*\";         // 0 or ...\r\n    var r_zero = \"0\";                    // string variable will be treated as pattern if there is no `@:skip`\r\n    var r_int = \"[1-9][0-9]*\";\r\n    var tok =  [                         // a rule set definition, the first one will become .token()\r\n        \"[ \\t]+\" =\u003e this.token(),\r\n        r_zero | r_int =\u003e CInt,          // zero or int\r\n     // inter + Opt(\"[eE][+-]?[0-9]+\")   // exponent\r\n        \"+\" =\u003e OpPlus,\r\n        \"-\" =\u003e OpMinus,\r\n        \"*\" =\u003e OpTimes,\r\n        \"/\" =\u003e OpDiv,\r\n        \"(\" =\u003e LParen,\r\n        \")\" =\u003e RParen,\r\n        \"[a-zA-Z_]+\" =\u003e CIdent,\r\n    ];\r\n}\r\n\r\n@:rule({\r\n    start: [main],            // Specify entrys, like the \"%start\" in ocamlyacc, If omitted then the first \"switch\" will be selected\r\n    left: [\"+\", \"-\"],         // The parser could auto reflect(str) =\u003e Token\r\n    left: [OpTimes, OpDiv],   // The lower have higher priority.\r\n    nonassoc: [UMINUS],       // The placeholder must be uppercase\r\n}) class Parser implements lm.SLR\u003cLexer\u003e {\r\n\r\n    var main = switch(s) {\r\n        case [e = expr, Eof]:\r\n            e;\r\n        default:              // place handling error code here\r\n            var t = stream.peek(0);\r\n            switch(t.term) {\r\n            case Eof:\r\n                return 0;\r\n            case CIdent:                // Show recovery from errors, Note: this ability is very weak\r\n                stream.junk(1);         // Discard current token\r\n                slrloop( -1, MAIN_EXP); // main =\u003e MAIN_EXP, NOTE: Only the entry switch-case (Specified in \"start\") has an EXP value\r\n            default:\r\n                throw \"Unexpected: \" + stream.str(t);\r\n            }\r\n    }\r\n\r\n    var expr : Int = switch(s) {        // Specify Type explicitly\r\n        case [e1 = expr, op = [OpPlus,OpMinus], e2 = expr]: op == OpPlus ? e1 + e2 : e1 - e2;\r\n        case [e1 = expr, OpTimes, e2 = expr]: e1 * e2;\r\n        case [e1 = expr, OpDiv, e2 = expr]: Std.int(e1 / e2);\r\n        case [LParen, e = expr, RParen]: e;\r\n        case [@:prec(UMINUS) OpMinus, e = expr]: -e;   // %prec UMINUS\r\n        case [CInt(n)]: n;\r\n    }\r\n\r\n    // Define custom extract function for CInt(n)\r\n    @:rule(CInt) inline function int_of_string( s : String ) : Int return Std.parseInt(s);\r\n    // OR @:rule(CInt) inline function int_of_string( input : lms.ByteData, t : lm.Stream.Tok ) : Int {\r\n    //    return Std.parseInt( input.readString(t.pmin, t.pmax - t.pmin) );\r\n    //}\r\n}\r\n\r\n```\r\n\r\ncompile:\r\n\r\n```bash\r\nhaxe -dce full -D analyzer-optimize -lib lex -main Demo -js demo.js\r\n```\r\n\r\n\u003cbr /\u003e\r\n\r\nGenerated JS:\r\n\r\n```js\r\n// Generated by Haxe 4.3.0-rc.1\r\n(function ($global) { \"use strict\";\r\nvar Demo = function() { };\r\nDemo.main = function() {\r\n    var str = \"1 - 2 * (3 + 4) + 5 * 6\";\r\n    var lex = new Lexer(str);\r\n    var par = new Parser(lex);\r\n    console.log(\"Demo.hx:9:\",par._entry(0,8) == 17);\r\n};\r\nvar Lexer = function(s) {\r\n    this.input = s;\r\n    this.pmin = 0;\r\n    this.pmax = 0;\r\n};\r\nLexer.prototype = {\r\n    getString: function(p,len) {\r\n        return this.input.substr(p,len);\r\n    }\r\n    ,_token: function(init,right) {\r\n        if(this.pmax \u003e= right) {\r\n            return 0;\r\n        }\r\n        var raw = Lexer.raw;\r\n        var i = this.pmax;\r\n        var state = init;\r\n        var prev = init;\r\n        var c;\r\n        while(i \u003c right) {\r\n            c = this.input.charCodeAt(i++);\r\n            state = raw.charCodeAt(128 * state + c);\r\n            if(state \u003e= 3) {\r\n                break;\r\n            }\r\n            prev = state;\r\n        }\r\n        this.pmin = i;\r\n        if(state == 255) {\r\n            state = prev;\r\n            --i;\r\n        }\r\n        var q = raw.charCodeAt(399 - state);\r\n        if(i \u003e this.pmax \u0026\u0026 q \u003c 8) {\r\n            this.pmin = this.pmax;\r\n            this.pmax = i;\r\n        } else {\r\n            q = raw.charCodeAt(399 - init);\r\n        }\r\n        return this.cases(q);\r\n    }\r\n    ,token: function() {\r\n        return this._token(0,this.input.length);\r\n    }\r\n    ,cases: function(s) {\r\n        switch(s) {\r\n        case 0:\r\n            return this._token(0,this.input.length);\r\n        case 1:\r\n            return 1;\r\n        case 2:\r\n            return 2;\r\n        case 3:\r\n            return 3;\r\n        case 4:\r\n            return 4;\r\n        case 5:\r\n            return 5;\r\n        case 6:\r\n            return 6;\r\n        case 7:\r\n            return 7;\r\n        default:\r\n            throw new Error(\"UnMatached: '\" + this.input.substr(this.pmax,this.pmin - this.pmax) + \"'\");\r\n        }\r\n    }\r\n};\r\nvar Parser = function(lex) {\r\n    this.stream = new lm_Stream(lex);\r\n};\r\nParser.prototype = {\r\n    _entry: function(state,exp) {\r\n        var t = this.stream.newTok(0,0,0);\r\n        t.state = state;\r\n        var _this = this.stream;\r\n        var i = _this.right;\r\n        while(--i \u003e= _this.pos) _this.cached[i + 1] = _this.cached[i];\r\n        _this.cached[_this.pos] = t;\r\n        ++_this.pos;\r\n        ++_this.right;\r\n        var raw = Parser.raw;\r\n        while(true) {\r\n            while(true) {\r\n                t = this.stream.next();\r\n                state = raw.charCodeAt(16 * state + t.term);\r\n                if(state \u003e= 9) {\r\n                    break;\r\n                }\r\n                t.state = state;\r\n            }\r\n            if(state == 255) {\r\n                this.stream.pos -= 1;\r\n                var _this = this.stream;\r\n                state = _this.cached[_this.pos + (-1)].state;\r\n            }\r\n            while(true) {\r\n                var q = raw.charCodeAt(159 - state);\r\n                var value = this.cases(q);\r\n                if(q \u003e= 7) {\r\n                    return value;\r\n                }\r\n                t = this.stream.reduce(Parser.lvs[q]);\r\n                if(t.term == exp) {\r\n                    this.stream.pos -= 2;\r\n                    this.stream.junk(2);\r\n                    return value;\r\n                }\r\n                t.val = value;\r\n                var _this1 = this.stream;\r\n                state = raw.charCodeAt(16 * _this1.cached[_this1.pos + (-2)].state + t.term);\r\n                t.state = state;\r\n                if(state \u003c 9) {\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    ,cases: function(q) {\r\n        var __s = this.stream;\r\n        switch(q) {\r\n        case 0:\r\n            return __s.cached[__s.pos + (-2)].val;\r\n        case 1:\r\n            var e1 = __s.cached[__s.pos + (-3)].val;\r\n            var e2 = __s.cached[__s.pos + (-1)].val;\r\n            if(__s.cached[__s.pos + (-2)].term == 2) {\r\n                return e1 + e2;\r\n            } else {\r\n                return e1 - e2;\r\n            }\r\n            break;\r\n        case 2:\r\n            return __s.cached[__s.pos + (-3)].val * __s.cached[__s.pos + (-1)].val;\r\n        case 3:\r\n            return __s.cached[__s.pos + (-3)].val / __s.cached[__s.pos + (-1)].val | 0;\r\n        case 4:\r\n            return __s.cached[__s.pos + (-2)].val;\r\n        case 5:\r\n            return -__s.cached[__s.pos + (-1)].val;\r\n        case 6:\r\n            return Std.parseInt(__s.stri(-1));\r\n        default:\r\n            var t = this.stream.peek(0);\r\n            throw new Error(\"Unexpected \\\"\" + (t.term != 0 ? this.stream.lex.getString(t.pmin,t.pmax - t.pmin) : \"Eof\") + \"\\\"\");\r\n        }\r\n    }\r\n};\r\nvar Std = function() { };\r\nStd.parseInt = function(x) {\r\n    var v = parseInt(x);\r\n    if(isNaN(v)) {\r\n        return null;\r\n    }\r\n    return v;\r\n};\r\nvar lm_Tok = function(t,min,max) {\r\n    this.term = t;\r\n    this.pmin = min;\r\n    this.pmax = max;\r\n};\r\nvar lm_Stream = function(l) {\r\n    this.lex = l;\r\n    var this1 = new Array(128);\r\n    this.cached = this1;\r\n    this.right = 0;\r\n    this.pos = 0;\r\n};\r\nlm_Stream.prototype = {\r\n    reclaim: function(tok) {\r\n        tok.nxt = this.h;\r\n        this.h = tok;\r\n    }\r\n    ,newTok: function(term,min,max) {\r\n        if(this.h == null) {\r\n            return new lm_Tok(term,min,max);\r\n        } else {\r\n            var t = this.h;\r\n            this.h = this.h.nxt;\r\n            t.term = term;\r\n            t.pmin = min;\r\n            t.pmax = max;\r\n            return t;\r\n        }\r\n    }\r\n    ,peek: function(i) {\r\n        while(this.right - this.pos \u003c= i) {\r\n            var t = this.lex.token();\r\n            this.cached[this.right++] = this.newTok(t,this.lex.pmin,this.lex.pmax);\r\n        }\r\n        return this.cached[this.pos + i];\r\n    }\r\n    ,junk: function(n) {\r\n        if(n \u003c= 0) {\r\n            return;\r\n        }\r\n        if(this.right - this.pos \u003e= n) {\r\n            var i = n;\r\n            while(i-- \u003e 0) this.reclaim(this.cached[this.pos + i]);\r\n            i = this.pos;\r\n            this.right -= n;\r\n            while(i \u003c this.right) {\r\n                this.cached[i] = this.cached[i + n];\r\n                ++i;\r\n            }\r\n        } else {\r\n            n -= this.right - this.pos;\r\n            while(n-- \u003e 0) this.lex.token();\r\n            while(this.right \u003e this.pos) this.reclaim(this.cached[--this.right]);\r\n        }\r\n    }\r\n    ,stri: function(dx) {\r\n        var t = this.cached[this.pos + dx];\r\n        return this.lex.getString(t.pmin,t.pmax - t.pmin);\r\n    }\r\n    ,next: function() {\r\n        if(this.right == this.pos) {\r\n            var t = this.lex.token();\r\n            this.cached[this.right++] = this.newTok(t,this.lex.pmin,this.lex.pmax);\r\n        }\r\n        return this.cached[this.pos++];\r\n    }\r\n    ,reduce: function(lvw) {\r\n        var w = lvw \u0026 255;\r\n        if(w == 0) {\r\n            return this.reduceEP(lvw \u003e\u003e\u003e 8);\r\n        }\r\n        var pmax = this.cached[this.pos + (-1)].pmax;\r\n        --w;\r\n        this.pos -= w;\r\n        this.right -= w;\r\n        var t = this.cached[this.pos + (-1)];\r\n        t.term = lvw \u003e\u003e\u003e 8;\r\n        t.pmax = pmax;\r\n        if(w == 0) {\r\n            return t;\r\n        }\r\n        var i = w;\r\n        while(i-- \u003e 0) this.reclaim(this.cached[this.pos + i]);\r\n        i = this.pos;\r\n        while(i \u003c this.right) {\r\n            this.cached[i] = this.cached[i + w];\r\n            ++i;\r\n        }\r\n        return t;\r\n    }\r\n    ,reduceEP: function(lv) {\r\n        var prev = this.cached[this.pos - 1];\r\n        var t = this.newTok(lv,prev.pmax,prev.pmax);\r\n        var i = this.right;\r\n        while(--i \u003e= this.pos) this.cached[i + 1] = this.cached[i];\r\n        this.cached[this.pos] = t;\r\n        ++this.pos;\r\n        ++this.right;\r\n        return t;\r\n    }\r\n};\r\nLexer.raw = \"ÿÿÿÿÿÿÿÿÿ\\x01ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\x01ÿÿÿÿÿÿÿ\\t\\x08\\x07\\x06ÿ\\x05ÿ\\x04\\x03\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\x01ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\x01ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ\\x06\\x07\\x04\\x02\\x03\\x05\\x01\\x01\\x00ÿ\";\r\nParser.raw = \"ÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\x08ÿÿÿÿÿÿÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\nÿÿÿÿÿÿÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\x03ÿÿÿÿÿÿÿÿ\\x04\\x04\\x06\\x07ÿ\\x0Bÿÿÿÿÿÿÿÿÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\x05ÿÿÿÿÿÿÿÿÿÿ\\x06\\x07ÿÿÿÿÿÿÿÿÿÿÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\rÿÿÿÿÿÿÿ\\x0Eÿ\\x01ÿÿ\\x02ÿÿ\\x0Cÿÿÿÿÿÿ\\tÿ\\x04\\x04\\x06\\x07ÿÿÿÿÿÿÿÿÿÿÿ\\x06\\x02\\x03\\x04\\x05\\x00ÿÿÿ\\x01ÿÿÿÿÿ\";\r\nParser.lvs = [2050,2307,2307,2307,2307,2306,2305];\r\nDemo.main();\r\n})({});\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr32%2Flex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr32%2Flex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr32%2Flex/lists"}