expressir 2.1.30 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +99 -0
- data/.github/workflows/links.yml +100 -0
- data/.github/workflows/rake.yml +4 -0
- data/.github/workflows/release.yml +11 -0
- data/.github/workflows/validate_schemas.yml +1 -1
- data/.gitignore +3 -0
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +267 -53
- data/Gemfile +2 -1
- data/README.adoc +993 -55
- data/docs/Gemfile +12 -0
- data/docs/_config.yml +141 -0
- data/docs/_guides/changes/changes-format.adoc +778 -0
- data/docs/_guides/changes/importing-eengine.adoc +898 -0
- data/docs/_guides/changes/index.adoc +396 -0
- data/docs/_guides/changes/programmatic-usage.adoc +1038 -0
- data/docs/_guides/changes/validating-changes.adoc +681 -0
- data/docs/_guides/cli/benchmark-performance.adoc +834 -0
- data/docs/_guides/cli/coverage-analysis.adoc +921 -0
- data/docs/_guides/cli/format-schemas.adoc +547 -0
- data/docs/_guides/cli/index.adoc +8 -0
- data/docs/_guides/cli/managing-changes.adoc +927 -0
- data/docs/_guides/cli/validate-ascii.adoc +645 -0
- data/docs/_guides/cli/validate-schemas.adoc +534 -0
- data/docs/_guides/formatter/formatter-architecture.adoc +401 -0
- data/docs/_guides/index.adoc +165 -0
- data/docs/_guides/ler/creating-packages.adoc +664 -0
- data/docs/_guides/ler/index.adoc +305 -0
- data/docs/_guides/ler/loading-packages.adoc +707 -0
- data/docs/_guides/ler/package-formats.adoc +748 -0
- data/docs/_guides/ler/querying-packages.adoc +826 -0
- data/docs/_guides/ler/validating-packages.adoc +750 -0
- data/docs/_guides/liquid/basic-templates.adoc +813 -0
- data/docs/_guides/liquid/documentation-generation.adoc +1042 -0
- data/docs/_guides/liquid/drops-reference.adoc +829 -0
- data/docs/_guides/liquid/filters-and-tags.adoc +912 -0
- data/docs/_guides/liquid/index.adoc +468 -0
- data/docs/_guides/manifests/creating-manifests.adoc +483 -0
- data/docs/_guides/manifests/index.adoc +307 -0
- data/docs/_guides/manifests/resolving-manifests.adoc +557 -0
- data/docs/_guides/manifests/validating-manifests.adoc +713 -0
- data/docs/_guides/ruby-api/formatting-schemas.adoc +605 -0
- data/docs/_guides/ruby-api/index.adoc +257 -0
- data/docs/_guides/ruby-api/parsing-files.adoc +421 -0
- data/docs/_guides/ruby-api/search-engine.adoc +609 -0
- data/docs/_guides/ruby-api/working-with-repository.adoc +577 -0
- data/docs/_pages/data-model.adoc +665 -0
- data/docs/_pages/express-language.adoc +506 -0
- data/docs/_pages/getting-started.adoc +414 -0
- data/docs/_pages/index.adoc +116 -0
- data/docs/_pages/introduction.adoc +256 -0
- data/docs/_pages/ler-packages.adoc +837 -0
- data/docs/_pages/parsers.adoc +709 -0
- data/docs/_pages/schema-manifests.adoc +431 -0
- data/docs/_references/index.adoc +228 -0
- data/docs/_tutorials/creating-ler-package.adoc +735 -0
- data/docs/_tutorials/documentation-coverage.adoc +795 -0
- data/docs/_tutorials/index.adoc +221 -0
- data/docs/_tutorials/liquid-templates.adoc +806 -0
- data/docs/_tutorials/parsing-your-first-schema.adoc +522 -0
- data/docs/_tutorials/querying-schemas.adoc +751 -0
- data/docs/_tutorials/working-with-multiple-schemas.adoc +676 -0
- data/docs/index.adoc +242 -0
- data/docs/lychee.toml +87 -0
- data/examples/demo_ler_usage.sh +86 -0
- data/examples/ler/README.md +111 -0
- data/examples/ler/simple_example.ler +0 -0
- data/examples/ler/simple_schema.exp +33 -0
- data/examples/ler_build.rb +75 -0
- data/examples/ler_cli.rb +79 -0
- data/examples/ler_demo_complete.rb +276 -0
- data/examples/ler_query.rb +91 -0
- data/examples/ler_query_examples.rb +305 -0
- data/examples/ler_stats.rb +81 -0
- data/examples/phase3_demo.rb +159 -0
- data/examples/query_demo_simple.rb +131 -0
- data/expressir.gemspec +4 -2
- data/lib/expressir/benchmark.rb +6 -6
- data/lib/expressir/cli.rb +21 -4
- data/lib/expressir/commands/format.rb +28 -0
- data/lib/expressir/commands/manifest.rb +427 -0
- data/lib/expressir/commands/package.rb +1274 -0
- data/lib/expressir/commands/validate.rb +70 -37
- data/lib/expressir/commands/validate_ascii.rb +607 -0
- data/lib/expressir/commands/validate_load.rb +88 -0
- data/lib/expressir/coverage.rb +15 -11
- data/lib/expressir/express/builder.rb +350 -0
- data/lib/expressir/express/builders/attribute_decl_builder.rb +38 -0
- data/lib/expressir/express/builders/built_in_builder.rb +88 -0
- data/lib/expressir/express/builders/constant_builder.rb +115 -0
- data/lib/expressir/express/builders/declaration_builder.rb +24 -0
- data/lib/expressir/express/builders/derive_clause_builder.rb +16 -0
- data/lib/expressir/express/builders/derived_attr_builder.rb +28 -0
- data/lib/expressir/express/builders/domain_rule_builder.rb +21 -0
- data/lib/expressir/express/builders/entity_decl_builder.rb +108 -0
- data/lib/expressir/express/builders/explicit_attr_builder.rb +52 -0
- data/lib/expressir/express/builders/expression_builder.rb +453 -0
- data/lib/expressir/express/builders/function_decl_builder.rb +84 -0
- data/lib/expressir/express/builders/helpers.rb +148 -0
- data/lib/expressir/express/builders/interface_builder.rb +171 -0
- data/lib/expressir/express/builders/inverse_attr_builder.rb +45 -0
- data/lib/expressir/express/builders/inverse_attr_type_builder.rb +36 -0
- data/lib/expressir/express/builders/inverse_clause_builder.rb +16 -0
- data/lib/expressir/express/builders/literal_builder.rb +107 -0
- data/lib/expressir/express/builders/procedure_decl_builder.rb +80 -0
- data/lib/expressir/express/builders/qualifier_builder.rb +128 -0
- data/lib/expressir/express/builders/reference_builder.rb +27 -0
- data/lib/expressir/express/builders/rule_decl_builder.rb +95 -0
- data/lib/expressir/express/builders/schema_body_decl_builder.rb +22 -0
- data/lib/expressir/express/builders/schema_decl_builder.rb +62 -0
- data/lib/expressir/express/builders/schema_version_builder.rb +40 -0
- data/lib/expressir/express/builders/simple_id_builder.rb +26 -0
- data/lib/expressir/express/builders/statement_builder.rb +250 -0
- data/lib/expressir/express/builders/subtype_constraint_builder.rb +188 -0
- data/lib/expressir/express/builders/syntax_builder.rb +19 -0
- data/lib/expressir/express/builders/token_builder.rb +15 -0
- data/lib/expressir/express/builders/type_builder.rb +264 -0
- data/lib/expressir/express/builders/type_decl_builder.rb +32 -0
- data/lib/expressir/express/builders/unique_clause_builder.rb +22 -0
- data/lib/expressir/express/builders/unique_rule_builder.rb +36 -0
- data/lib/expressir/express/builders/where_clause_builder.rb +22 -0
- data/lib/expressir/express/builders.rb +43 -0
- data/lib/expressir/express/error.rb +18 -2
- data/lib/expressir/express/formatter.rb +23 -1509
- data/lib/expressir/express/formatters/data_types_formatter.rb +317 -0
- data/lib/expressir/express/formatters/declarations_formatter.rb +689 -0
- data/lib/expressir/express/formatters/expressions_formatter.rb +160 -0
- data/lib/expressir/express/formatters/literals_formatter.rb +46 -0
- data/lib/expressir/express/formatters/references_formatter.rb +42 -0
- data/lib/expressir/express/formatters/remark_formatter.rb +296 -0
- data/lib/expressir/express/formatters/remark_item_formatter.rb +25 -0
- data/lib/expressir/express/formatters/statements_formatter.rb +224 -0
- data/lib/expressir/express/formatters/supertype_expressions_formatter.rb +48 -0
- data/lib/expressir/express/parser.rb +155 -7
- data/lib/expressir/express/pretty_formatter.rb +624 -0
- data/lib/expressir/express/remark_attacher.rb +1155 -0
- data/lib/expressir/express/resolve_references_model_visitor.rb +1 -0
- data/lib/expressir/express/streaming_builder.rb +467 -0
- data/lib/expressir/express/transformer/remark_handling.rb +196 -0
- data/lib/expressir/manifest/resolver.rb +213 -0
- data/lib/expressir/manifest/validator.rb +195 -0
- data/lib/expressir/model/declarations/entity.rb +6 -0
- data/lib/expressir/model/dependency_resolver.rb +270 -0
- data/lib/expressir/model/identifier.rb +1 -1
- data/lib/expressir/model/indexes/entity_index.rb +103 -0
- data/lib/expressir/model/indexes/reference_index.rb +148 -0
- data/lib/expressir/model/indexes/type_index.rb +149 -0
- data/lib/expressir/model/interface_validator.rb +384 -0
- data/lib/expressir/model/model_element.rb +30 -2
- data/lib/expressir/model/remark_info.rb +51 -0
- data/lib/expressir/model/repository.rb +400 -5
- data/lib/expressir/model/repository_validator.rb +295 -0
- data/lib/expressir/model/search_engine.rb +574 -0
- data/lib/expressir/model.rb +4 -94
- data/lib/expressir/package/builder.rb +200 -0
- data/lib/expressir/package/metadata.rb +81 -0
- data/lib/expressir/package/reader.rb +165 -0
- data/lib/expressir/schema_manifest.rb +11 -1
- data/lib/expressir/version.rb +1 -1
- data/lib/expressir.rb +20 -3
- metadata +168 -9
- data/docs/benchmarking.adoc +0 -107
- data/docs/liquid_drops.adoc +0 -1547
- data/lib/expressir/express/visitor.rb +0 -2815
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Express
|
|
3
|
+
module StatementsFormatter
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def format_statements_alias(node)
|
|
7
|
+
[
|
|
8
|
+
[
|
|
9
|
+
"ALIAS",
|
|
10
|
+
" ",
|
|
11
|
+
node.id,
|
|
12
|
+
" ",
|
|
13
|
+
"FOR",
|
|
14
|
+
" ",
|
|
15
|
+
format(node.expression),
|
|
16
|
+
";",
|
|
17
|
+
].join,
|
|
18
|
+
*if node.statements&.length&.positive?
|
|
19
|
+
indent(node.statements.map { |x| format(x) }.join("\n"))
|
|
20
|
+
end,
|
|
21
|
+
*format_remarks(node),
|
|
22
|
+
[
|
|
23
|
+
"END_ALIAS",
|
|
24
|
+
";",
|
|
25
|
+
].join,
|
|
26
|
+
].join("\n")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def format_statements_assignment(node)
|
|
30
|
+
[
|
|
31
|
+
format(node.ref),
|
|
32
|
+
" ",
|
|
33
|
+
":=",
|
|
34
|
+
" ",
|
|
35
|
+
format(node.expression),
|
|
36
|
+
";",
|
|
37
|
+
].join
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def format_statements_procedure_call(node)
|
|
41
|
+
[
|
|
42
|
+
format(node.procedure),
|
|
43
|
+
*if node.parameters&.length&.positive?
|
|
44
|
+
[
|
|
45
|
+
"(",
|
|
46
|
+
node.parameters.map { |x| format(x) }.join(", "),
|
|
47
|
+
")",
|
|
48
|
+
].join
|
|
49
|
+
end,
|
|
50
|
+
";",
|
|
51
|
+
].join
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def format_statements_case(node)
|
|
55
|
+
[
|
|
56
|
+
[
|
|
57
|
+
"CASE",
|
|
58
|
+
" ",
|
|
59
|
+
format(node.expression),
|
|
60
|
+
" ",
|
|
61
|
+
"OF",
|
|
62
|
+
].join,
|
|
63
|
+
*if node.actions&.length&.positive?
|
|
64
|
+
node.actions.map { |x| format(x) }
|
|
65
|
+
end,
|
|
66
|
+
*if node.otherwise_statement
|
|
67
|
+
[
|
|
68
|
+
[
|
|
69
|
+
"OTHERWISE",
|
|
70
|
+
" ",
|
|
71
|
+
":",
|
|
72
|
+
].join,
|
|
73
|
+
indent(format(node.otherwise_statement)),
|
|
74
|
+
]
|
|
75
|
+
end,
|
|
76
|
+
[
|
|
77
|
+
"END_CASE",
|
|
78
|
+
";",
|
|
79
|
+
].join,
|
|
80
|
+
].join("\n")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def format_statements_case_action(node)
|
|
84
|
+
node.labels ||= []
|
|
85
|
+
[
|
|
86
|
+
[
|
|
87
|
+
node.labels.map { |x| format(x) }.join(", "),
|
|
88
|
+
" ",
|
|
89
|
+
":",
|
|
90
|
+
].join,
|
|
91
|
+
indent(format(node.statement)),
|
|
92
|
+
].join("\n")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def format_statements_compound(node)
|
|
96
|
+
node.statements ||= []
|
|
97
|
+
[
|
|
98
|
+
"BEGIN",
|
|
99
|
+
*if node.statements&.length&.positive?
|
|
100
|
+
indent(node.statements.map { |x| format(x) }.join("\n"))
|
|
101
|
+
end,
|
|
102
|
+
[
|
|
103
|
+
"END",
|
|
104
|
+
";",
|
|
105
|
+
].join,
|
|
106
|
+
].join("\n")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def format_statements_escape(_node)
|
|
110
|
+
[
|
|
111
|
+
"ESCAPE",
|
|
112
|
+
";",
|
|
113
|
+
].join
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def format_statements_if(node)
|
|
117
|
+
[
|
|
118
|
+
[
|
|
119
|
+
"IF",
|
|
120
|
+
" ",
|
|
121
|
+
format(node.expression),
|
|
122
|
+
" ",
|
|
123
|
+
"THEN",
|
|
124
|
+
].join,
|
|
125
|
+
*if node.statements&.length&.positive?
|
|
126
|
+
indent(node.statements.map { |x| format(x) }.join("\n"))
|
|
127
|
+
end,
|
|
128
|
+
*if node.else_statements&.length&.positive?
|
|
129
|
+
[
|
|
130
|
+
"ELSE",
|
|
131
|
+
indent(node.else_statements.map { |x| format(x) }.join("\n")),
|
|
132
|
+
].join("\n")
|
|
133
|
+
end,
|
|
134
|
+
[
|
|
135
|
+
"END_IF",
|
|
136
|
+
";",
|
|
137
|
+
].join,
|
|
138
|
+
].join("\n")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def format_statements_null(_node)
|
|
142
|
+
";"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def format_statements_repeat(node)
|
|
146
|
+
node.statements ||= []
|
|
147
|
+
[
|
|
148
|
+
[
|
|
149
|
+
"REPEAT",
|
|
150
|
+
*if node.id
|
|
151
|
+
[
|
|
152
|
+
" ",
|
|
153
|
+
node.id,
|
|
154
|
+
" ",
|
|
155
|
+
":=",
|
|
156
|
+
" ",
|
|
157
|
+
format(node.bound1),
|
|
158
|
+
" ",
|
|
159
|
+
"TO",
|
|
160
|
+
" ",
|
|
161
|
+
format(node.bound2),
|
|
162
|
+
*if node.increment
|
|
163
|
+
[
|
|
164
|
+
" ",
|
|
165
|
+
"BY",
|
|
166
|
+
" ",
|
|
167
|
+
format(node.increment),
|
|
168
|
+
].join
|
|
169
|
+
end,
|
|
170
|
+
].join
|
|
171
|
+
end,
|
|
172
|
+
*if node.while_expression
|
|
173
|
+
[
|
|
174
|
+
" ",
|
|
175
|
+
"WHILE",
|
|
176
|
+
" ",
|
|
177
|
+
format(node.while_expression),
|
|
178
|
+
].join
|
|
179
|
+
end,
|
|
180
|
+
*if node.until_expression
|
|
181
|
+
[
|
|
182
|
+
" ",
|
|
183
|
+
"UNTIL",
|
|
184
|
+
" ",
|
|
185
|
+
format(node.until_expression),
|
|
186
|
+
].join
|
|
187
|
+
end,
|
|
188
|
+
";",
|
|
189
|
+
].join,
|
|
190
|
+
*if node.statements&.length&.positive?
|
|
191
|
+
indent(node.statements.map { |x| format(x) }.join("\n"))
|
|
192
|
+
end,
|
|
193
|
+
*format_remarks(node),
|
|
194
|
+
[
|
|
195
|
+
"END_REPEAT",
|
|
196
|
+
";",
|
|
197
|
+
].join,
|
|
198
|
+
].join("\n")
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def format_statements_return(node)
|
|
202
|
+
[
|
|
203
|
+
"RETURN",
|
|
204
|
+
*if node.expression
|
|
205
|
+
[
|
|
206
|
+
" ",
|
|
207
|
+
"(",
|
|
208
|
+
format(node.expression),
|
|
209
|
+
")",
|
|
210
|
+
].join
|
|
211
|
+
end,
|
|
212
|
+
";",
|
|
213
|
+
].join
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def format_statements_skip(_node)
|
|
217
|
+
[
|
|
218
|
+
"SKIP",
|
|
219
|
+
";",
|
|
220
|
+
].join
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Expressir
|
|
2
|
+
module Express
|
|
3
|
+
module SupertypeExpressionsFormatter
|
|
4
|
+
private
|
|
5
|
+
|
|
6
|
+
def format_supertype_expressions_binary_supertype_expression(node)
|
|
7
|
+
supertype_precedence = self.class.const_get(:SUPERTYPE_OPERATOR_PRECEDENCE)
|
|
8
|
+
op1_higher_precedence = node.operand1.is_a?(Model::SupertypeExpressions::BinarySupertypeExpression) &&
|
|
9
|
+
(supertype_precedence[node.operand1.operator] > supertype_precedence[node.operator])
|
|
10
|
+
op2_higher_precedence = node.operand2.is_a?(Model::SupertypeExpressions::BinarySupertypeExpression) &&
|
|
11
|
+
(supertype_precedence[node.operand2.operator] > supertype_precedence[node.operator])
|
|
12
|
+
|
|
13
|
+
[
|
|
14
|
+
*if op1_higher_precedence
|
|
15
|
+
"("
|
|
16
|
+
end,
|
|
17
|
+
format(node.operand1),
|
|
18
|
+
*if op1_higher_precedence
|
|
19
|
+
")"
|
|
20
|
+
end,
|
|
21
|
+
" ",
|
|
22
|
+
case node.operator
|
|
23
|
+
when Model::SupertypeExpressions::BinarySupertypeExpression::AND then "AND"
|
|
24
|
+
when Model::SupertypeExpressions::BinarySupertypeExpression::ANDOR then "ANDOR"
|
|
25
|
+
end,
|
|
26
|
+
" ",
|
|
27
|
+
*if op2_higher_precedence
|
|
28
|
+
"("
|
|
29
|
+
end,
|
|
30
|
+
format(node.operand2),
|
|
31
|
+
*if op2_higher_precedence
|
|
32
|
+
")"
|
|
33
|
+
end,
|
|
34
|
+
].join
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def format_supertype_expressions_oneof_supertype_expression(node)
|
|
38
|
+
node.operands ||= []
|
|
39
|
+
[
|
|
40
|
+
"ONEOF",
|
|
41
|
+
"(",
|
|
42
|
+
node.operands.map { |x| format(x) }.join(", "),
|
|
43
|
+
")",
|
|
44
|
+
].join
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,12 +1,79 @@
|
|
|
1
|
-
require "
|
|
1
|
+
require "parsanol"
|
|
2
2
|
require_relative "error"
|
|
3
|
+
require_relative "builder"
|
|
4
|
+
require_relative "builders"
|
|
5
|
+
require_relative "remark_attacher"
|
|
6
|
+
require_relative "streaming_builder"
|
|
3
7
|
|
|
4
8
|
module Expressir
|
|
5
9
|
module Express
|
|
6
10
|
class Parser
|
|
7
|
-
class Parser <
|
|
11
|
+
class Parser < Parsanol::Parser
|
|
8
12
|
root(:syntax)
|
|
9
13
|
|
|
14
|
+
# Cache for native parser grammar (class-level)
|
|
15
|
+
@@cached_grammar_json = nil
|
|
16
|
+
@@cached_grammar_atom_id = nil
|
|
17
|
+
|
|
18
|
+
# Cache for parser instance (avoids ~7ms overhead of Parser.new)
|
|
19
|
+
@@cached_parser = nil
|
|
20
|
+
@@parser_mutex = Mutex.new
|
|
21
|
+
|
|
22
|
+
# Get cached parser instance (thread-safe)
|
|
23
|
+
# Reusing the parser avoids the overhead of reinitializing all rule definitions
|
|
24
|
+
def self.cached_parser
|
|
25
|
+
return @@cached_parser if @@cached_parser
|
|
26
|
+
|
|
27
|
+
@@parser_mutex.synchronize do
|
|
28
|
+
@@cached_parser ||= new
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Clear the cached parser (useful for testing or after grammar changes)
|
|
33
|
+
def self.clear_parser_cache
|
|
34
|
+
@@parser_mutex.synchronize do
|
|
35
|
+
@@cached_parser = nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Check if native parsing is available
|
|
40
|
+
def self.native_available?
|
|
41
|
+
return @native_available unless @native_available.nil?
|
|
42
|
+
|
|
43
|
+
@native_available = begin
|
|
44
|
+
require "parsanol/native"
|
|
45
|
+
Parsanol::Native.available?
|
|
46
|
+
rescue LoadError
|
|
47
|
+
false
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Get cached grammar JSON for native parsing
|
|
52
|
+
def self.cached_grammar_json
|
|
53
|
+
return @@cached_grammar_json if @@cached_grammar_json
|
|
54
|
+
|
|
55
|
+
parser = new
|
|
56
|
+
atom = parser.syntax
|
|
57
|
+
|
|
58
|
+
# Cache by atom object_id
|
|
59
|
+
if atom.object_id != @@cached_grammar_atom_id
|
|
60
|
+
@@cached_grammar_atom_id = atom.object_id
|
|
61
|
+
@@cached_grammar_json = Parsanol::Native.serialize_grammar(atom)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@@cached_grammar_json
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Parse using native engine (with caching)
|
|
68
|
+
def self.parse_native(source)
|
|
69
|
+
unless native_available?
|
|
70
|
+
raise LoadError, "Native parser not available"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Use Parsanol 2.0 API - parse returns Slice objects with position info
|
|
74
|
+
new.parse(source, mode: :native)
|
|
75
|
+
end
|
|
76
|
+
|
|
10
77
|
def cts(atom)
|
|
11
78
|
spaces >> atom
|
|
12
79
|
end
|
|
@@ -610,15 +677,14 @@ module Expressir
|
|
|
610
677
|
schema_file = root_path ? Pathname.new(file.to_s).relative_path_from(root_path).to_s : file.to_s
|
|
611
678
|
|
|
612
679
|
begin
|
|
613
|
-
ast = Parser.
|
|
614
|
-
rescue
|
|
680
|
+
ast = Parser.cached_parser.parse source
|
|
681
|
+
rescue Parsanol::ParseFailed => e
|
|
615
682
|
# Instead of just printing, raise a proper error with file context
|
|
616
683
|
raise Error::SchemaParseFailure.new(schema_file, e)
|
|
617
684
|
end
|
|
618
685
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
@repository = visitor.visit_ast ast, :top
|
|
686
|
+
@repository = Builder.build_with_remarks(ast, source: source,
|
|
687
|
+
include_source: include_source)
|
|
622
688
|
|
|
623
689
|
@repository.schemas.each do |schema|
|
|
624
690
|
schema.file = schema_file
|
|
@@ -680,6 +746,88 @@ root_path: nil)
|
|
|
680
746
|
|
|
681
747
|
@repository
|
|
682
748
|
end
|
|
749
|
+
|
|
750
|
+
# Parses Express content string into an Express model
|
|
751
|
+
# @param [String] content Express content as string
|
|
752
|
+
# @param [Boolean] skip_references skip resolving references
|
|
753
|
+
# @param [Boolean] include_source attach original source code to model elements
|
|
754
|
+
# @param [Boolean] use_native use native parser if available (default: false - AST format differs slightly)
|
|
755
|
+
# @param [Boolean] use_streaming use streaming builder for maximum performance (default: false)
|
|
756
|
+
# @return [Model::Repository] Parsed repository
|
|
757
|
+
# @raise [SchemaParseFailure] if the content fails to parse
|
|
758
|
+
def self.from_exp(content, skip_references: nil, include_source: nil,
|
|
759
|
+
use_native: false, use_streaming: false)
|
|
760
|
+
# Streaming builder mode - uses Parsanol streaming callbacks
|
|
761
|
+
if use_streaming && Parser.native_available? && defined?(Parsanol::Native.parse_with_builder)
|
|
762
|
+
return from_exp_streaming(content, skip_references: skip_references,
|
|
763
|
+
include_source: include_source)
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
begin
|
|
767
|
+
# Use cached parser instance for performance (avoids ~7ms Parser.new overhead)
|
|
768
|
+
ast = if use_native && Parser.native_available?
|
|
769
|
+
Parser.parse_native(content)
|
|
770
|
+
else
|
|
771
|
+
Parser.cached_parser.parse(content)
|
|
772
|
+
end
|
|
773
|
+
rescue Parsanol::ParseFailed, StandardError => e
|
|
774
|
+
raise Error::SchemaParseFailure.new("(from string)", e)
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
repository = Builder.build_with_remarks(ast, source: content,
|
|
778
|
+
include_source: include_source)
|
|
779
|
+
|
|
780
|
+
repository.schemas.each do |schema|
|
|
781
|
+
schema.file = nil
|
|
782
|
+
schema.file_basename = nil
|
|
783
|
+
schema.formatted = schema.to_s(no_remarks: true)
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
unless skip_references
|
|
787
|
+
Expressir::Benchmark.measure_references do
|
|
788
|
+
resolve_references_model_visitor = ResolveReferencesModelVisitor.new
|
|
789
|
+
resolve_references_model_visitor.visit(repository)
|
|
790
|
+
end
|
|
791
|
+
end
|
|
792
|
+
|
|
793
|
+
repository
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
# Parse using streaming builder (maximum performance)
|
|
797
|
+
# @param [String] content Express content as string
|
|
798
|
+
# @param [Boolean] skip_references skip resolving references
|
|
799
|
+
# @param [Boolean] include_source attach original source code to model elements
|
|
800
|
+
# @return [Model::Repository] Parsed repository
|
|
801
|
+
# @raise [SchemaParseFailure] if the content fails to parse
|
|
802
|
+
def self.from_exp_streaming(content, skip_references: nil,
|
|
803
|
+
include_source: nil)
|
|
804
|
+
grammar_json = Parser.cached_grammar_json
|
|
805
|
+
builder = StreamingBuilder.new(source: content,
|
|
806
|
+
include_source: include_source)
|
|
807
|
+
|
|
808
|
+
begin
|
|
809
|
+
repository = Parsanol::Native.parse_with_builder(grammar_json,
|
|
810
|
+
content, builder)
|
|
811
|
+
rescue StandardError => e
|
|
812
|
+
raise Error::SchemaParseFailure.new("(streaming)", e)
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
repository.schemas.each do |schema|
|
|
816
|
+
schema.file = nil
|
|
817
|
+
schema.file_basename = nil
|
|
818
|
+
schema.formatted = schema.to_s(no_remarks: true)
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
unless skip_references
|
|
822
|
+
Expressir::Benchmark.measure_references do
|
|
823
|
+
resolve_references_model_visitor = ResolveReferencesModelVisitor.new
|
|
824
|
+
resolve_references_model_visitor.visit(repository)
|
|
825
|
+
end
|
|
826
|
+
end
|
|
827
|
+
|
|
828
|
+
repository
|
|
829
|
+
end
|
|
830
|
+
private_class_method :from_exp_streaming
|
|
683
831
|
end
|
|
684
832
|
end
|
|
685
833
|
end
|