{"id":20111950,"url":"https://github.com/mezoni/peg","last_synced_at":"2026-02-27T15:31:54.980Z","repository":{"id":275357007,"uuid":"925840838","full_name":"mezoni/peg","owner":"mezoni","description":"Command line tool for generating a PEG (with some syntactic sugar) parsers","archived":false,"fork":false,"pushed_at":"2025-02-27T06:17:02.000Z","size":723,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-05T00:59:09.055Z","etag":null,"topics":["dart","parser","parser-generator","peg"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mezoni.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-01T21:45:47.000Z","updated_at":"2025-02-27T06:17:05.000Z","dependencies_parsed_at":"2025-02-01T23:18:36.496Z","dependency_job_id":"ceea6f18-5d56-4e0d-b570-0a0af9f08e01","html_url":"https://github.com/mezoni/peg","commit_stats":null,"previous_names":["mezoni/peg"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mezoni/peg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mezoni%2Fpeg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mezoni%2Fpeg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mezoni%2Fpeg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mezoni%2Fpeg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mezoni","download_url":"https://codeload.github.com/mezoni/peg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mezoni%2Fpeg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29901749,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T14:46:13.553Z","status":"ssl_error","status_checked_at":"2026-02-27T14:46:10.522Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["dart","parser","parser-generator","peg"],"created_at":"2024-11-13T18:18:18.110Z","updated_at":"2026-02-27T15:31:54.946Z","avatar_url":"https://github.com/mezoni.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# peg\n\nCommand line tool for generating a PEG (with some syntactic sugar) parsers\n\nVersion: 9.0.1\n\n[![Pub Package](https://img.shields.io/pub/v/peg.svg)](https://pub.dev/packages/peg)\n[![GitHub Issues](https://img.shields.io/github/issues/mezoni/peg.svg)](https://github.com/mezoni/peg/issues)\n[![GitHub Forks](https://img.shields.io/github/forks/mezoni/peg.svg)](https://github.com/mezoni/peg/forks)\n[![GitHub Stars](https://img.shields.io/github/stars/mezoni/peg.svg)](https://github.com/mezoni/peg/stargazers)\n[![GitHub License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://raw.githubusercontent.com/mezoni/peg/main/LICENSE)\n\n## About this software\n\nThis software does not contain a public API because it is a console application (command line tool).  \nThis tool is intended to generate the source code of PEG parsers.  \nBefore using this tool, it is necessary to activate it using the package manager `pub`.\n\n## Activation and usage\n\nTo activate this command line tool, run the following command:\n\n```bash\ndart pub global activate peg\n```\n\nAfter activation, you can use the following command to use the command line tool:\n\n```bash\ndart pub global run peg\n```\n\n## Structure of the grammar definition file\n\nThis generator generates itself from a grammar written using its own syntax.  \nFor a more detailed familiarization with the syntax, it is recommended to familiarize yourself with the syntax of the grammar used to generate this PEG parser.  \n[peg.peg](https://github.com/mezoni/peg/blob/main/lib/src/peg_parser/peg.peg)\n\nGrammar declaration is made using sections, like sections for a preprocessor, but at the same time, it should be noted that preprocessing is not performed and grammar processing (parsing) occurs in one stage.  \n\n3 sections are used to declare the grammar:\n\n- Section for declaring directives and global members\n- Section for declaring members of instances of the parser class\n- Section for declaring grammar rules\n\nExample of a grammar declaration:\n\n```text\n%{\n\nimport 'foo.dart';\n\n}%\n\n%%\n\nconst SimpleParser();\n\n%%\n\nA =\u003e [A-Za-z]*\n\n```\n\nThe grammar must contain at least one production rule, which means that using a section to declare grammar rules is mandatory. The use of other sections is optional and is determined by the actual needs based on the chosen method of declaring the grammar.\n\n## Parsing expression grammar\n\nIn computer science, a parsing expression grammar (PEG) is a type of analytic formal grammar, i.e. it describes a formal language in terms of a set of rules for recognizing strings in the language.  \nThis information is from the Wikipedia website.  \n[Parsing expression grammar](https://en.wikipedia.org/wiki/Parsing_expression_grammar)  \n\nEverything that can be found on the Wikipedia website will not be described in detail here.  \nHere will described only the additional features, the ways of their use and the implementation details.  \n\nMore detailed information can also be found on the Bryan Ford website.\n[Parsing Expression Grammars: A Recognition-Based Syntactic Foundation](https://bford.info/pub/lang/peg/)\n\n## Main characteristics\n\nMain characteristics:\n\n- Small size of runtime source code\n- Small size of the source code of generated parsers\n- Generating quite good quality and optimal parser code\n- Automatic generation of standard errors\n- Possibility of a declarative way of describing additional errors\n- Additional useful features, including the use of syntactic sugar\n\nCreating a parser using PEG is very simple.  \nThere is no need to use tokenization.  \nThe PEG grammar definition is a combination of parsing expressions (similar to regular expressions), production rules, and regular Dart code.  \n\n### Available examples\n\nA trivial implementation of the formula evaluator (calculator):  \nGrammar definition: [calc.peg](https://github.com/mezoni/peg/blob/main/example/calc.peg)  \nGenerated code: [example.dart](https://github.com/mezoni/peg/blob/main/example/example.dart)  \nDartPad example: [https://dartpad.dev/?id=d720a249b378462ba36490956213225c](https://dartpad.dev/?id=d720a249b378462ba36490956213225c)\n\nThe same formula evaluator, but a little faster.  \nGrammar definition:  [realtime_calc.peg](https://github.com/mezoni/peg/blob/main/example/realtime_calc.peg)  \nGenerated code: [realtime_calc.dart](https://github.com/mezoni/peg/blob/main/example/realtime_calc.dart)\n\nMathematical formula evaluator with support for variables and functions.  \nThis example was written in about 30 minutes, based on the code from the calculator example.  \nGrammar definition:  [math.peg](https://github.com/mezoni/peg/blob/main/example/math.peg)  \nGenerated code: [math_parser.dart](https://github.com/mezoni/peg/blob/main/example/math_parser.dart)  \nDartPad example: [https://dartpad.dev/?id=fa7cbeb8dec40ad043937a09523141d3](https://dartpad.dev/?id=fa7cbeb8dec40ad043937a09523141d3)\n\nA number parser and an example of how to examine the generated error messages.  \nGrammar definition: [number.peg](https://github.com/mezoni/peg/blob/main/example/number.peg)  \nGenerated code: [number.dart](https://github.com/mezoni/peg/blob/main/example/number.dart)\n\nA fully functional example of a JSON parser.  \nGrammar definition:  [json.peg](https://github.com/mezoni/peg/blob/main/example/json.peg)  \nGenerated code: [json_example.dart](https://github.com/mezoni/peg/blob/main/example/json_example.dart)\n\n## A few words about code generation\n\nBranching operations can generate `dead code` if the algorithms is illogical.  \nSuch generated code does not mean that it is a bug in the code generator or a bug in the parser generator.  \nThis may well and most often be a mistake in the logic of grammar (for example, an incorrect algorithm for performing a parsing operation).  \nFor example, in the expression `OrderedChoice`, any optional expression, unless it is the last expression, will cause all subsequent expressions to never be executed, because the given expression always succeeds.  \nIn this case, dead code will be generated uncompromisingly, that is, by itself, according to the logic of the code generator, which knows nothing about the parser generator and the grammar itself.\n\n## Automatic error generation\n\nAutomatic error generation occurs when parsing the following grammar elements:\n\n- The `literal` expression with `single quotes`\n- Production rule that specifies the name of a `grammar element`\n\nThese grammar elements generate the errors `expected` and `unexpected`, if they are parsed with the parent expression `not predicate`.\n\nThese elements cover most of the needs for standard error messages.\n\nThe literal expression with `double quotes` is the opposite of literal with `single quotes`.  \nIt performs the same operations, but silently (without generating errors).  \nThis is very convenient when the `expected` or `unexpected` error is out of place and even incorrect.  \n\nThe most common and simple example when it is 100% necessary:\n\n- `\"\\r\\n\"`\n\nBecause it is unlikely that a grammar element with such a name `'\\r\\n'` and action (`line break`) is `expected`, if it is parsed as `white space`.\n\nThe literal expression with `double quotes`and the expression `character class` can be considered `primitive` `terminal` expressions. They only signal with `failures` in case of unsuccessful parsing.\n\n### What can be done to ensure that more errors are generated automatically?\n\nThe main recommendation is that the expression single quoted `literal` expression **must always** be used for punctuation marks.  \nDo not use `primitive terminals` for these purposes under any circumstances.  \nWrong use: `[,]`, `[(]`, `\":\"`, `\";\"` etc.\n\nPunctuation marks may include the following types (as an example):\n\n- Separators `:`, `,`,  `|`\n- Terminators `;`\n- Opening and closing marks `{`, `}`, `[`, `]`, `{`, `}`,\n- Surrounding marks `\"`, `'`\n\nNot recommended for use with `operators` because they are not expected.  \nGood use: [+] [*] \"~/\" \"??\"\n\nThe following example demonstrates the use of the `operand` and `separator`:\n\n```text\nBooleanExpression \"?\" S Expression ':' S Expression\n```\n\nIn this case, the `separator` is always an expected element of the grammar.\n\nWhen developing a parser, it is always possible to examine what errors the parser produces.  \nAnd make adjustments to grammar if necessary.  \nBecause the grammar that parses expressions is not unambiguous and it does not know the purpose of certain elements.  \n\nBy following these principles, you can ensure that error messages are of sufficient quality.  \n\n## Declarative way of generating errors\n\nTo generate additional errors, to increase the amount of information about the causes of failures, there is a declarative way to specify when, where and how to generate errors.  \nIt allows to generate errors with any messages.  \n\nThe point of this method is that the error handler description specifies the parameters for generating an error.  \nFor these purposes, the expression `Catch` is used, which will be described below in the corresponding section.  \n\nBelow is a list of error parameters:\n\n- `message`\n- `origin`\n- `start`\n- `end`\n\nThe `message` parameter specifies the text of the error message.\n\nExample:\n\n```text\nExpression Sequence\n~ { message = 'Some error message' }\n```\n\nThe `origin` parameter specifies the condition under which the error will be generated.  \nThere are two conditions:\n\n- `== start`\n- `!= start`\n\nThat is, this condition specifies where the failure should occur so that the error was generated, in the `starting` position or further than the `starting` position.  \nIf the `origin` parameter is not specified, the error will be generated regardless of where the failure occurred.\n\nExample:\n\n```text\nExpression Sequence\n~ { message = 'Malformed element' origin != start }\n```\n\nThe `start` and `end` parameters specify what information about the error location will be registered.  \nThese parameters determine what portion of the input data will be displayed in the error message.  \nThere are two values for both parameters:\n\n- `start`\n- `end`\n\nEssentially, this is information about the location where the error occurred (`source span` or simply `location`).  \nBy default, the `source span` is registered. That is, `start` = `start`, `end` = `end`.  \nIf an invalid combination of values ​​is specified, default values ​​will be applied.  \n\nExample:\n\n```text\nExpression Sequence\n~ { message = 'Message at the end of the failure position' start = end }\n```\n\n```text\nFoo\n  ^\n```\n\n```text\nExpression Sequence\n~ { message = 'Message at the start of the failure position' end = start }\n```\n\n```text\nFoo\n^\n```\n\n```text\nExpression Sequence\n~ { message = 'Message with source span' }\n```\n\n```text\nFoo\n^^^\n```\n\n## Additional features\n\nThis implementation adds additional features.  \nBelow is a short list of additional features:\n\n- Action expression\n- Predicate expression\n- Match expression\n- Catch expression (error handler)\n- Sematic variable\n- Special semantic result variable `$`\n- Modified character class\n- Typing expression\n- Syntactic sugar\n\nSome small and simple examples of additional features.\n\n### Action expression\n\nThe expression `Action` allow to execute any code and are mainly used for computing and assigning the result of parsing.  \nSyntax: `{` block of statements `}`\n\n```text\n`bool`\nBoolean('boolean') =\u003e\n  $ = { $$ = false; }\n  ('false' / 'true' { $ = true; })\n  S\n```\n\nThis example demonstrates the use of 2 blocks of source code.\n\n```text\n{ $$ = false; }\n```\n\n```text\n{ $ = true; }\n```\n\nThis is the regular source code that will be embedded into the parser code.\n\n### Predicate expressions\n\nThe expression `Predicate` allow to determining the success or failure of the parsing based on the value of the specified boolean expression.  \nSyntax: `\u0026{` boolean expression `}` or `!{` boolean expression `}`\n\nExample:\n\n```text\nRule =\u003e\n  Expr1\n  ! { state.position == position }\n  Expr2\n```\n\nThis expression will fail if the result of the expression `state.position == position` will be evaluated as `true`.\n\n### Match expressions\n\nThe `Match` expression returns a string value of the data source that matches the recognized expression.  \nSyntax: `\u003c` recognition expression `\u003e`\n\n```text\nType('type') =\u003e\n  '`'\n  $ = \u003c\n    @while (*) {\n      ! [`] [a-zA-Z0-9_$\u003c({,:})\u003e? ]\n    }\n  \u003e\n  '`' S\n```\n\n### Catch expressions (error handlers)\n\nThe `Catch`expression allows to generate errors when parsing fails in preceding expressions.  \nThe `Catch` expression allows to specify when, where, and how to generate errors based on the specified parameters.  \nThe description of the parameters is given above in the text.  \nSyntax: sequence expression `~ {` error parameters `}`\n\nExample:\n\n```text\nA B C ~ { message = 'foo' }\n```\n\nThe `Catch`expression can only be used at the end of the expression `Sequence`, as the last expression of the sequence.\n\n`GOOD`\n\n```text\nA B C ~ { message = 'foo' }\n```\n\n`WRONG`\n\n```text\nA B C ~ { message = 'foo' } C\n```\n\n### Sematic variables\n\nSemantic variables allow to assign the results of expressions to variables for later use.  \nSyntax: `n :` Expression or `n =` Expression\n\nExample:\n\n```text\nn = { $$ = true; var x = 5; }\n\nn  = { true }\n```\n\n**Convention**.  \nWhen a semantic variable is used with the `Action` expression (that is, with a code block), then the following rule applies.  \nIf a code block contains the character sequence `$$` (in any form), it is assumed that the intermediate variable `$$` is used, in which case this variable should be assigned the value.  \n\nExamples:\n\n`GOOD`\n\n```text\nn = { $$ = true; }\n\nn = { $$ = r'$$'; }\n\nn = { true }\n```\n\n`WRONG`\n\n```text\nn = { r'$$' }\n```\n\nAssignment without using the intermediate variable `$$` will not perform any other computations.  \nBelow are examples of generated code.  \n\n```dart\nfinal String $$;\n$$ = String.fromCharCode(int.parse(s, radix: 16));\nString $ = $$;\n\nString $ = String.fromCharCode(int.parse(s, radix: 16));\n```\n\n### Special semantic result variable `$`\n\nSpecial semantic result variable `$` allow to assign the results of expressions.\n\nBelow is an example of what the result of the sequence expression will be.\n\n```text\n# B\nA = B\n\n# B\nA = b:B\n\n# No result\nA = B C\n\n# No result\nA = b:B C\n\n# No result\nA = B c:C\n\n# No result\nA = b:B c:C\n\n# $\nA = $:B c:C\n\n# $\nA = b:B $:C\n```\n\nIf a special semantic result variable `$` is used, the value of this variable will be used as the result.\n\n### Modified character class\n\nThe modified `Character class` expression allows for more readable character range specifications and inverting ranges (negation).\nSyntax: `[` ranges `]` or `[^` ranges `]`\n\nThe `negated` character class `[^]` is equivalent to the following sequence of expressions but much more faster:\n\n```text\n! [unexpected characters]\n$ = .\n```\n\nAdditional features:\n\n```text\n[^0-9]\n\n[{20-21}{23-5b}{5d-10ffff}]\n\n[\\u{20}-\\u{21}\\u{23}-\\u{5b}\\u{5d}-\\u{10ffff}]\n```\n\n### Typing expression\n\nThe expression `Typing` allows you to explicitly specify the type of the expression's result.  \nSyntax:  `Type` expression\n\nExample:\n\n```text\n`Type` n = { $$ = 41; }\n\n`Type` { $$ = 41; }\n\n`num` result = { $$ = num.parse(integer); }\n```\n\nThis expression can be useful for subexpressions, to explicitly specify the type.\n\n### Syntactic sugar\n\nThe `@while` expressions is syntactic sugar:\n\n- `@while(*)` `{` e `}` it is syntactic sugar for e`*`\n- `@while(+)` `{` e `}` it is syntactic sugar for e`+`\n\n```text\n`List\u003cObject?\u003e`\nValues =\u003e\n  e = Value\n  { final l = [e]; }\n  @while (*) {\n    ',' S\n    e = Value\n    { l.add(e); }\n  }\n  $ = { $$ = l; }\n```\n\nThe `-` operator is syntactic sugar for the operator `/`  \nThe `-` character can be repeated as many times as necessary.\n\n```text\n`Expression`\nAssignment =\u003e\n  v = (Identifier / $ = '$' S)\n  ('=' S / ':' S)\n  e = Prefix\n  $ = { $$ = VariableExpression(expression: e, name: v); }\n  ----\n  Prefix\n```\n\n```text\n`Expression`\nSuffix =\u003e\n  $ = Primary\n  (\n    '*' S { $ = ZeroOrMoreExpression(expression: $); }\n    ----\n    '+' S { $ = OneOrMoreExpression(expression: $); }\n    ----\n    '?' S { $ = OptionalExpression(expression: $); }\n  )?\n```\n\n## How to parse?\n\nAn example of how parsing can be implemented.\n\n```dart\nExpression? parse(String source) {\n  final parser = MyParser();\n  final state = State(source);\n  final result = parser.parseStart(state);\n  if (result == null) {\n    final file = SourceFile.fromString(source);\n    throw FormatException(state\n        .getErrors()\n        .map((e) =\u003e file.span(e.start, e.end).message(e.message))\n        .join('\\n'));\n  }\n\n  return result .$1;\n}\n```\n\nThis requires the use of the `source_span` package.  \nThis method can be generated automatically by specifying the \"parse\" command line option.  \n\nExample\n\n```bash\n dart pub global run peg bin/scanner.peg --parse=parse\n```\n\nIf it is not desirable to use third-party libraries, then it can be done this way (using only `FormatException`).\n\n```dart\nExpression? parse(String source) {\n  final parser = MyParser();\n  final state = State(source);\n  final result = parser.parseStart(state);\n  if (result == null) {\n    final messages = \u003cString\u003e[];\n    for (final error in state.getErrors()) {\n      final message = error.message;\n      final start = error.start;\n      final exception = FormatException(message, source, start);\n      messages.add('$exception'.substring('FormatException'.length));\n    }\n\n    throw FormatException(messages.join('\\n\\n'));\n  }\n\n  return result .$1;\n}\n```\n\nUnfortunately `FormatException` only support `offset` and this does not allow the use of `start` and  `end` at the same time.  \nPerhaps in the future the Dart SDK developers will improve this method a little by adding the `end` parameter. Such care for Dart SDK users would be invaluable.\n\n## Example of a simple calculator\n\n```text\n%{\n// ignore_for_file: prefer_conditional_assignment, prefer_final_locals\n\nimport 'package:source_span/source_span.dart';\n\nvoid main() {\n  const source = ' 1 + 2 * 3 + x ';\n  final result = calc(source, {'x': 5});\n  print(result);\n}\n\nint calc(String source, Map\u003cString, int\u003e vars) {\n  final parser = CalcParser(vars);\n  final state = State(source);\n  final result = parser.parseStart(state);\n  if (result == null) {\n    final file = SourceFile.fromString(source);\n    throw FormatException(state\n        .getErrors()\n        .map((e) =\u003e file.span(e.start, e.end).message(e.message))\n        .join('\\n'));\n  }\n\n  return result.$1;\n}\n\n}%\n\n%%\n\nMap\u003cString, int\u003e vars = {};\n\nCalcParser(this.vars);\n\n%%\n\n`int`\nStart =\u003e\n  S\n  $ = Expr\n  EOF\n\n`int`\nExpr('expression') =\u003e\n  Sum\n\n`int`\nSum =\u003e\n  $ = Product\n  @while (*) {\n    [+] S\n    r = Product\n    { $ += r; }\n    ----\n    [-] S\n    r = Product\n    { $ -= r; }\n  }\n\n`int`\nProduct =\u003e\n  $ = Value\n  @while (*) {\n    [*] S\n    r = Value\n    { $ *= r; }\n    ----\n    [/] S\n    r = Value\n    { $ ~/= r; }\n  }\n\n`int`\nValue('expression') =\u003e (\n  NUMBER\n  ----\n  i = ID\n  $ = { $$ = vars[i]!; }\n  ----\n  '(' S\n  $ = Expr\n  ')' S\n)\n\n`int`\nNUMBER =\u003e\n  n = \u003c[0-9]+\u003e\n  S\n  $ = { $$ = int.parse(n); }\n\n`String`\nID =\u003e\n  $ = \u003c[a-zA-Z]\u003e\n  S\n\n`void`\nEOF('end of file') =\u003e\n  ! .\n\n`void`\nS =\u003e [ \\t\\r\\n]*\n\n```\n\n## Errors when generating a parser from a grammar\n\nWhen developing grammar, mistakes are inevitable.  \nTo minimize errors, the parser generator analyzes the grammar for errors.  \nErrors can be of the following kinds:\n\n- Syntax error\n- Errors in determining the type of the expression result\n- Errors when there are no rules to which references are given\n- Type mismatch errors in source code\n\n### Syntax error\n\nThis type of error is occurred when the syntax is not followed. To correct it, it is required to follow the syntax.\n\n### Errors in determining the type of the expression result\n\nIn certain cases, the grammar analyzer can determine the type of an expression or production rule.  \nBut this is not possible in all cases.  \n\nThere are several cases when this cannot be done:\n\n- Expression `Action`: always\n- Expression `Ordered choice`: alternatives have different types\n\nIf the result value is not specified, the default value is `void`.\n\nAll this needs to be corrected.  \n\nIf this happens for some other reason, then it is required to solve it in a radical way, by explicitly specifying the return type for the production rule.  \n\nExample:\n\n```text\n`RuleType`\nRule =\u003e Expr\n```\n\nThe easiest way is to specify types for all problematic `rules` for which the type is not determined automatically.  \nBut this can be done a little more complicated, but more correctly.  \nStart specifying types for those rules on which the types of other rules depend.  \nThat is, from the bottom up.  \n\nBut if you don't want to do this, then just specify all the types of rules that are not defined (and not determined) manually.\n\n### Errors when there are no rules to which references are given\n\nThis indicates that such a rule does not exist or the rule name is misspelled.\n\n### Type mismatch errors in source code\n\nThis means that either the result type was not determined automatically, or it was specified manually incorrectly.\n\n## Generating a parser programmatically\n\nGenerating a parser programmatically is possible, but it is not recommended.  \nOnly in exceptional cases. For example, for testing purposes.  \nIt is not recommended to include this package in the list of `dependencies`.  \nIt is acceptable to include this package in the list of `dev_dependencies`.\n\nBelow is an example of how this can be done.\n\n```dart\nimport 'dart:io';\n\nimport 'package:peg/src/parser_generator.dart';\n\nvoid main(List\u003cString\u003e args) {\n  final parsers = [\n    (\n      'example/calc.peg',\n      'example/example.dart',\n      ParserGeneratorOptions(\n        name: 'CalcParser',\n      ),\n    ),\n    (\n      'example/realtime_calc.peg',\n      'example/realtime_calc.dart',\n      ParserGeneratorOptions(\n        name: 'CalcParser',\n      ),\n    ),\n    (\n      'example/number.peg',\n      'example/number.dart',\n      ParserGeneratorOptions(\n        name: 'NumberParser',\n        parseFunction: 'parse',\n      ),\n    ),\n  ];\n  final outputFiles = \u003cString\u003e[];\n  for (final parser in parsers) {\n    final inputFile = parser.$1;\n    final outputFile = parser.$2;\n    final options = parser.$3;\n    final source = File(inputFile).readAsStringSync();\n    final generator = ParserGenerator(\n      options: options,\n      source: source,\n    );\n    final result = generator.generate();\n    final diagnostics = generator.diagnostics;\n    for (final error in diagnostics.errors) {\n      print('$error\\n');\n    }\n\n    for (final warning in diagnostics.warnings) {\n      print('$warning\\n');\n    }\n\n    if (diagnostics.hasErrors) {\n      exit(-1);\n    }\n\n    outputFiles.add(outputFile);\n    File(outputFile).writeAsStringSync(result);\n  }\n\n  Process.runSync(Platform.executable, ['format', ...outputFiles]);\n}\n\n```\n\n## Is it possible to parse from files?\n\nYes, it is possible.  \nThe generated parser does not use direct access to the input data.  \nAccess to data is provided through members of class `State`.  \nList of these members:\n\n- `charSize`\n- `peek`\n- `startsWith`\n- `strlen`\n- `substring`\n\nThus, by creating a new class that extends the `State` class and overwriting these methods, it is possible to perform the parsing from the file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmezoni%2Fpeg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmezoni%2Fpeg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmezoni%2Fpeg/lists"}