synthra 0.1.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 +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +40 -0
- data/.yardopts +18 -0
- data/ACCESS_DOCS.md +116 -0
- data/ADVANCED_FEATURES_SUMMARY.md +245 -0
- data/CHANGELOG.md +498 -0
- data/CODE_OF_CONDUCT.md +122 -0
- data/CONTRIBUTING.md +307 -0
- data/DOCUMENTATION.md +204 -0
- data/DOCUMENTATION_GUIDE.md +194 -0
- data/LICENSE +22 -0
- data/README.md +1458 -0
- data/Rakefile +128 -0
- data/benchmark/README.md +591 -0
- data/benchmark/batch_generation.rb +63 -0
- data/benchmark/engine_comparison.rb +295 -0
- data/benchmark/single_record.rb +108 -0
- data/benchmark/streaming.rb +74 -0
- data/docs/ACTIVERECORD_INFERENCE.md +524 -0
- data/docs/API_SERVER.md +278 -0
- data/docs/CONFIG_FILE.md +315 -0
- data/docs/DATA_CONTRACTS.md +312 -0
- data/docs/ENHANCED_REPL.md +304 -0
- data/docs/FACTORY_BOT.md +271 -0
- data/docs/GITHUB_ACTION.md +420 -0
- data/docs/GRAPHQL_EXPORT.md +303 -0
- data/docs/GRAPHQL_FEDERATION.md +651 -0
- data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
- data/docs/LSP.md +189 -0
- data/docs/MIGRATION_GENERATOR.md +547 -0
- data/docs/MOCK_SERVER.md +280 -0
- data/docs/NATIVE_ENGINE.md +298 -0
- data/docs/OPENAPI_EXPORT.md +252 -0
- data/docs/PERFORMANCE_MODE.md +228 -0
- data/docs/PERSONAS.md +547 -0
- data/docs/PROPERTY_TESTING.md +284 -0
- data/docs/PROTOBUF_EXPORT.md +276 -0
- data/docs/QUALITY_METRICS.md +555 -0
- data/docs/QUICK_REFERENCE.md +88 -0
- data/docs/RAILS_ENGINE.md +404 -0
- data/docs/RAILS_INTEGRATION.md +454 -0
- data/docs/README.md +175 -0
- data/docs/REPL_QUICK_REFERENCE.md +149 -0
- data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
- data/docs/SCENARIOS.md +576 -0
- data/docs/SECURITY_TESTING.md +318 -0
- data/docs/SNAPSHOT_TESTING.md +308 -0
- data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
- data/docs/TERRAFORM_EXPORT.md +447 -0
- data/docs/TIME_TRAVEL.md +507 -0
- data/docs/USAGE_GUIDE.md +980 -0
- data/docs/WEBHOOK_SIMULATOR.md +579 -0
- data/docs/advanced_features.md +183 -0
- data/docs/api_reference.md +153 -0
- data/docs/behaviors.md +138 -0
- data/docs/best_practices.md +191 -0
- data/docs/dsl_reference.md +172 -0
- data/docs/examples.md +162 -0
- data/docs/generation_modes.md +125 -0
- data/docs/getting_started.md +92 -0
- data/docs/index.html +177 -0
- data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
- data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
- data/docs/troubleshooting.md +215 -0
- data/docs/type_reference.md +224 -0
- data/examples/hostile_mode_demo.rb +64 -0
- data/exe/synthra +6 -0
- data/ext/synthra_native/Cargo.lock +972 -0
- data/ext/synthra_native/Cargo.toml +46 -0
- data/ext/synthra_native/extconf.rb +41 -0
- data/ext/synthra_native/src/generator.rs +397 -0
- data/ext/synthra_native/src/lib.rs +229 -0
- data/ext/synthra_native/src/types.rs +1485 -0
- data/lib/generators/synthra/install_generator.rb +86 -0
- data/lib/generators/synthra/templates/api_response.dsl +15 -0
- data/lib/generators/synthra/templates/fake_data.rake +116 -0
- data/lib/generators/synthra/templates/synthra.yml +31 -0
- data/lib/generators/synthra/templates/synthra_support.rb +19 -0
- data/lib/generators/synthra/templates/user.dsl +11 -0
- data/lib/synthra/activerecord_inference.rb +394 -0
- data/lib/synthra/api.rb +381 -0
- data/lib/synthra/api_server.rb +718 -0
- data/lib/synthra/behaviors/applicator.rb +165 -0
- data/lib/synthra/behaviors/base.rb +155 -0
- data/lib/synthra/behaviors/close_connection.rb +60 -0
- data/lib/synthra/behaviors/deprecated.rb +100 -0
- data/lib/synthra/behaviors/failure.rb +69 -0
- data/lib/synthra/behaviors/latency.rb +103 -0
- data/lib/synthra/behaviors/partial_data.rb +83 -0
- data/lib/synthra/behaviors/randomize_order.rb +74 -0
- data/lib/synthra/behaviors/registry.rb +238 -0
- data/lib/synthra/behaviors/simulate_error.rb +79 -0
- data/lib/synthra/cli/commands/base.rb +105 -0
- data/lib/synthra/cli/commands/diff.rb +227 -0
- data/lib/synthra/cli/commands/docs.rb +67 -0
- data/lib/synthra/cli/commands/export.rb +150 -0
- data/lib/synthra/cli/commands/generate.rb +72 -0
- data/lib/synthra/cli/commands/import.rb +80 -0
- data/lib/synthra/cli/commands/lint.rb +53 -0
- data/lib/synthra/cli/commands/live.rb +57 -0
- data/lib/synthra/cli/commands/seed.rb +99 -0
- data/lib/synthra/cli/commands/validate.rb +28 -0
- data/lib/synthra/cli.rb +2471 -0
- data/lib/synthra/config_file.rb +129 -0
- data/lib/synthra/configuration.rb +281 -0
- data/lib/synthra/contracts_registry.rb +408 -0
- data/lib/synthra/database_seeder.rb +268 -0
- data/lib/synthra/deterministic_ids.rb +218 -0
- data/lib/synthra/documentation_generator.rb +414 -0
- data/lib/synthra/engine.rb +251 -0
- data/lib/synthra/errors.rb +1169 -0
- data/lib/synthra/export/base.rb +85 -0
- data/lib/synthra/export/csv.rb +101 -0
- data/lib/synthra/export/graphql.rb +266 -0
- data/lib/synthra/export/graphql_federation.rb +377 -0
- data/lib/synthra/export/graphviz.rb +258 -0
- data/lib/synthra/export/javascript.rb +327 -0
- data/lib/synthra/export/json_data.rb +61 -0
- data/lib/synthra/export/json_schema.rb +290 -0
- data/lib/synthra/export/openapi.rb +514 -0
- data/lib/synthra/export/protobuf.rb +483 -0
- data/lib/synthra/export/python.rb +560 -0
- data/lib/synthra/export/sql.rb +381 -0
- data/lib/synthra/export/sql_insert.rb +152 -0
- data/lib/synthra/export/terraform.rb +501 -0
- data/lib/synthra/export/type_mapping.rb +389 -0
- data/lib/synthra/export/typescript.rb +300 -0
- data/lib/synthra/export/xml_data.rb +104 -0
- data/lib/synthra/export/yaml_data.rb +56 -0
- data/lib/synthra/export.rb +404 -0
- data/lib/synthra/factory_bot_integration.rb +157 -0
- data/lib/synthra/field.rb +440 -0
- data/lib/synthra/functions/registry.rb +104 -0
- data/lib/synthra/generator/context.rb +372 -0
- data/lib/synthra/generator/engine.rb +336 -0
- data/lib/synthra/generator/faker_adapter.rb +425 -0
- data/lib/synthra/generator/modes.rb +444 -0
- data/lib/synthra/generator/resolver.rb +256 -0
- data/lib/synthra/generator/rng.rb +273 -0
- data/lib/synthra/generator/streamer.rb +63 -0
- data/lib/synthra/generator/uniqueness.rb +118 -0
- data/lib/synthra/initializer.rb +97 -0
- data/lib/synthra/limits.rb +279 -0
- data/lib/synthra/live_preview.rb +518 -0
- data/lib/synthra/loader_config.rb +78 -0
- data/lib/synthra/lsp/server.rb +689 -0
- data/lib/synthra/migration_generator.rb +301 -0
- data/lib/synthra/mixin.rb +174 -0
- data/lib/synthra/mock_server.rb +458 -0
- data/lib/synthra/native_engine.rb +304 -0
- data/lib/synthra/openapi_importer.rb +228 -0
- data/lib/synthra/output/json_formatter.rb +40 -0
- data/lib/synthra/output/ndjson_formatter.rb +55 -0
- data/lib/synthra/parser/ast.rb +1287 -0
- data/lib/synthra/parser/lexer.rb +1152 -0
- data/lib/synthra/parser/parser.rb +1664 -0
- data/lib/synthra/parser/tokens.rb +461 -0
- data/lib/synthra/performance_mode.rb +364 -0
- data/lib/synthra/personas.rb +397 -0
- data/lib/synthra/property_testing.rb +172 -0
- data/lib/synthra/quality_metrics.rb +405 -0
- data/lib/synthra/rails_test_helper.rb +248 -0
- data/lib/synthra/registry.rb +533 -0
- data/lib/synthra/relationships.rb +193 -0
- data/lib/synthra/repl/enhanced_repl.rb +607 -0
- data/lib/synthra/repl/formatter.rb +191 -0
- data/lib/synthra/scenarios.rb +423 -0
- data/lib/synthra/schema.rb +605 -0
- data/lib/synthra/schema_inheritance.rb +104 -0
- data/lib/synthra/schema_versioning.rb +212 -0
- data/lib/synthra/snapshot_testing.rb +199 -0
- data/lib/synthra/time_travel.rb +338 -0
- data/lib/synthra/type_definitions.rb +274 -0
- data/lib/synthra/types/address_location/addresses.rb +125 -0
- data/lib/synthra/types/address_location/airports.rb +200 -0
- data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
- data/lib/synthra/types/address_location/locations.rb +406 -0
- data/lib/synthra/types/base.rb +48 -0
- data/lib/synthra/types/commerce_products/commerce.rb +119 -0
- data/lib/synthra/types/commerce_products/companies.rb +71 -0
- data/lib/synthra/types/commerce_products/construction.rb +126 -0
- data/lib/synthra/types/commerce_products/products.rb +205 -0
- data/lib/synthra/types/core/collections.rb +513 -0
- data/lib/synthra/types/core/defaults.rb +76 -0
- data/lib/synthra/types/core/enums.rb +102 -0
- data/lib/synthra/types/core/identifiers.rb +445 -0
- data/lib/synthra/types/core/primitives.rb +586 -0
- data/lib/synthra/types/core/references.rb +466 -0
- data/lib/synthra/types/core/sequences.rb +304 -0
- data/lib/synthra/types/crypto/crypto.rb +162 -0
- data/lib/synthra/types/date_time/dates.rb +387 -0
- data/lib/synthra/types/finance_banking/banking.rb +424 -0
- data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
- data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
- data/lib/synthra/types/formula.rb +184 -0
- data/lib/synthra/types/health_medical/medical.rb +150 -0
- data/lib/synthra/types/hostile_payloads.rb +122 -0
- data/lib/synthra/types/json_array.rb +51 -0
- data/lib/synthra/types/media_entertainment/media.rb +62 -0
- data/lib/synthra/types/naughty_string.rb +30 -0
- data/lib/synthra/types/personal_names/chinese.rb +41 -0
- data/lib/synthra/types/personal_names/identifiers.rb +187 -0
- data/lib/synthra/types/personal_names/names.rb +246 -0
- data/lib/synthra/types/personal_names/national_id.rb +89 -0
- data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
- data/lib/synthra/types/regex.rb +248 -0
- data/lib/synthra/types/registry.rb +182 -0
- data/lib/synthra/types/repeating_element.rb +50 -0
- data/lib/synthra/types/scenario.rb +29 -0
- data/lib/synthra/types/technology_internet/apps.rb +67 -0
- data/lib/synthra/types/technology_internet/communication.rb +162 -0
- data/lib/synthra/types/technology_internet/devices.rb +80 -0
- data/lib/synthra/types/technology_internet/formats.rb +139 -0
- data/lib/synthra/types/technology_internet/networking.rb +143 -0
- data/lib/synthra/types/template.rb +92 -0
- data/lib/synthra/types/text_content/business.rb +128 -0
- data/lib/synthra/types/text_content/colors.rb +70 -0
- data/lib/synthra/types/text_content/misc.rb +237 -0
- data/lib/synthra/types/text_content/security.rb +130 -0
- data/lib/synthra/types/text_content/text_generation.rb +532 -0
- data/lib/synthra/types/travel/travel.rb +150 -0
- data/lib/synthra/utils/string_distance.rb +133 -0
- data/lib/synthra/validator/dsl_validator.rb +339 -0
- data/lib/synthra/validator/path_validator.rb +615 -0
- data/lib/synthra/version.rb +35 -0
- data/lib/synthra/webhook_simulator.rb +341 -0
- data/lib/synthra.rb +259 -0
- data/schemas/address.dsl +16 -0
- data/schemas/api_response.dsl +8 -0
- data/schemas/error_payload.dsl +9 -0
- data/schemas/order.dsl +10 -0
- data/schemas/order_item.dsl +8 -0
- data/schemas/payment.dsl +11 -0
- data/schemas/social_post.dsl +13 -0
- data/schemas/user.dsl +10 -0
- data/scripts/batch_fix_all.rb +96 -0
- data/scripts/delete_old_files.rb +32 -0
- data/scripts/fix_all_grouped_files.rb +137 -0
- data/scripts/fix_all_indentation.rb +48 -0
- data/scripts/fix_all_syntax.rb +124 -0
- data/scripts/fix_grouped_files.rb +184 -0
- data/scripts/fix_syntax_errors.rb +108 -0
- data/scripts/group_domain_types.rb +112 -0
- data/scripts/group_domain_types_fixed.rb +150 -0
- data/scripts/merge_domains_to_one_file.rb +68 -0
- data/scripts/move_existing_types.rb +130 -0
- data/scripts/split_grouped_types.rb +142 -0
- data/tech_docs/README.md +134 -0
- data/tech_docs/advanced/streaming.md +405 -0
- data/tech_docs/advanced/thread_safety.md +253 -0
- data/tech_docs/api/overview.md +485 -0
- data/tech_docs/appendices/type_chart.md +193 -0
- data/tech_docs/basic_concepts.md +383 -0
- data/tech_docs/behaviors/overview.md +346 -0
- data/tech_docs/dsl/complex_types.md +790 -0
- data/tech_docs/dsl/core_types.md +464 -0
- data/tech_docs/dsl/datetime_types.md +325 -0
- data/tech_docs/dsl/field_modifiers.md +414 -0
- data/tech_docs/dsl/grammar.md +431 -0
- data/tech_docs/dsl/schema_definition.md +399 -0
- data/tech_docs/export/README.md +276 -0
- data/tech_docs/installation.md +273 -0
- data/tech_docs/integration/ci_cd.md +707 -0
- data/tech_docs/integration/ci_cd_guide.md +579 -0
- data/tech_docs/integration/factory_bot.md +485 -0
- data/tech_docs/integration/rails.md +630 -0
- data/tech_docs/integration/rspec.md +449 -0
- data/tech_docs/modes/overview.md +350 -0
- data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
- data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
- data/tech_docs/quick_start.md +256 -0
- data/tech_docs/templates/README.md +805 -0
- data/tech_docs/tutorials/advanced.md +371 -0
- data/tech_docs/tutorials/getting_started.md +189 -0
- data/tech_docs/tutorials/intermediate.md +231 -0
- data/tech_docs/tutorials/template_gallery.md +569 -0
- data/tech_example/01_basic_usage.rb +238 -0
- data/tech_example/02_types_demo.rb +336 -0
- data/tech_example/04_cli_usage.md +429 -0
- data/tech_example/05_database_seeding.rb +283 -0
- data/tech_example/07_rspec_integration.rb +359 -0
- data/tech_example/10_custom_types.rb +387 -0
- data/tech_example/12_behaviors.rb +372 -0
- data/tech_example/13_twitter_dm_example.rb +120 -0
- data/tech_example/14_exact_json_structure.rb +253 -0
- data/tech_example/16_lsp_server.rb +56 -0
- data/tech_example/17_property_testing.rb +92 -0
- data/tech_example/18_enhanced_repl.rb +120 -0
- data/tech_example/19_security_fuzzing.rb +145 -0
- data/tech_example/NEW_FEATURES.md +169 -0
- data/tech_example/README.md +118 -0
- data/tech_example/schemas/api_response.dsl +123 -0
- data/tech_example/schemas/ecommerce.dsl +121 -0
- data/tech_example/schemas/twitter_dm.dsl +109 -0
- data/tech_example/schemas/user.dsl +36 -0
- data/vscode-extension/README.md +246 -0
- data/vscode-extension/language-configuration.json +31 -0
- data/vscode-extension/package.json +55 -0
- data/vscode-extension/snippets/fakedatadsl.json +198 -0
- data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
- metadata +478 -0
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# Synthra Token Definitions
|
|
6
|
+
# =============================================================================
|
|
7
|
+
#
|
|
8
|
+
# This file defines all token types recognized by the DSL lexer and the
|
|
9
|
+
# Token class used to represent individual tokens.
|
|
10
|
+
#
|
|
11
|
+
# The lexer converts DSL source text into a stream of Token objects,
|
|
12
|
+
# which the parser then uses to build an AST.
|
|
13
|
+
#
|
|
14
|
+
# @example Token stream for "User:"
|
|
15
|
+
# Token(:schema_name, "User", line: 1, column: 1)
|
|
16
|
+
# Token(:colon, ":", line: 1, column: 5)
|
|
17
|
+
#
|
|
18
|
+
# @example Token stream for "name: text"
|
|
19
|
+
# Token(:field_name, "name", line: 2, column: 3)
|
|
20
|
+
# Token(:colon, ":", line: 2, column: 7)
|
|
21
|
+
# Token(:type, "text", line: 2, column: 9)
|
|
22
|
+
#
|
|
23
|
+
# =============================================================================
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
module Synthra
|
|
27
|
+
module Parser
|
|
28
|
+
|
|
29
|
+
# Token type constants for the DSL lexer
|
|
30
|
+
#
|
|
31
|
+
# This module defines all the token types that the lexer can produce.
|
|
32
|
+
# Each token type is a symbol that identifies the kind of syntax element.
|
|
33
|
+
#
|
|
34
|
+
# Token types are organized into categories:
|
|
35
|
+
# - **Structural**: Schema and field names, colons, question marks
|
|
36
|
+
# - **Types**: Type names, Ref keyword
|
|
37
|
+
# - **Delimiters**: Parentheses, commas, dots
|
|
38
|
+
# - **Values**: Numbers, strings, identifiers, ranges, percentages
|
|
39
|
+
# - **Keywords**: if, true, false
|
|
40
|
+
# - **Behaviors**: @ prefixed behavior declarations
|
|
41
|
+
# - **Whitespace/Structure**: Newlines, indentation changes
|
|
42
|
+
# - **Special**: EOF, symbols
|
|
43
|
+
#
|
|
44
|
+
# @example Check if a token is a type
|
|
45
|
+
# token.type == Tokens::TYPE
|
|
46
|
+
#
|
|
47
|
+
# @example Check if token type is valid
|
|
48
|
+
# Tokens::ALL.include?(:type) # => true
|
|
49
|
+
#
|
|
50
|
+
|
|
51
|
+
module Tokens
|
|
52
|
+
# ==========================================================================
|
|
53
|
+
|
|
54
|
+
# Structural Tokens
|
|
55
|
+
# ==========================================================================
|
|
56
|
+
# These tokens define the structure of schemas and fields
|
|
57
|
+
|
|
58
|
+
# Schema name at the top level (e.g., "User:")
|
|
59
|
+
# Value: String containing the schema name without the colon
|
|
60
|
+
# @example "User:" => Token(:schema_name, "User")
|
|
61
|
+
|
|
62
|
+
SCHEMA_NAME = :schema_name
|
|
63
|
+
|
|
64
|
+
# Field name within a schema (e.g., "name:", "email?:")
|
|
65
|
+
# Value: String containing the field name (may include ? for optional)
|
|
66
|
+
# @example "email?:" => Token(:field_name, "email?")
|
|
67
|
+
|
|
68
|
+
FIELD_NAME = :field_name
|
|
69
|
+
|
|
70
|
+
# Colon separator
|
|
71
|
+
# Value: ":" literal
|
|
72
|
+
# @example ":" => Token(:colon, ":")
|
|
73
|
+
|
|
74
|
+
COLON = :colon
|
|
75
|
+
|
|
76
|
+
# Question mark for optional/nullable types
|
|
77
|
+
# Value: "?" literal
|
|
78
|
+
# @example "?" => Token(:question, "?")
|
|
79
|
+
|
|
80
|
+
QUESTION = :question
|
|
81
|
+
|
|
82
|
+
# ==========================================================================
|
|
83
|
+
|
|
84
|
+
# Type Tokens
|
|
85
|
+
# ==========================================================================
|
|
86
|
+
# These tokens represent type declarations
|
|
87
|
+
|
|
88
|
+
# Built-in or custom type name (uuid, text, number, etc.)
|
|
89
|
+
# Value: String containing the type name
|
|
90
|
+
# @example "uuid" => Token(:type, "uuid")
|
|
91
|
+
|
|
92
|
+
TYPE = :type
|
|
93
|
+
|
|
94
|
+
# Reference keyword for cross-schema references
|
|
95
|
+
# Value: "Ref" literal
|
|
96
|
+
# @example "Ref" => Token(:ref, "Ref")
|
|
97
|
+
|
|
98
|
+
REF = :ref
|
|
99
|
+
|
|
100
|
+
# ==========================================================================
|
|
101
|
+
|
|
102
|
+
# Delimiter Tokens
|
|
103
|
+
# ==========================================================================
|
|
104
|
+
# These tokens separate or group elements
|
|
105
|
+
|
|
106
|
+
# Left parenthesis for type arguments
|
|
107
|
+
# Value: "(" literal
|
|
108
|
+
# @example "(" => Token(:lparen, "(")
|
|
109
|
+
|
|
110
|
+
LPAREN = :lparen
|
|
111
|
+
|
|
112
|
+
# Right parenthesis for type arguments
|
|
113
|
+
# Value: ")" literal
|
|
114
|
+
# @example ")" => Token(:rparen, ")")
|
|
115
|
+
|
|
116
|
+
RPAREN = :rparen
|
|
117
|
+
|
|
118
|
+
# Comma separator in argument lists
|
|
119
|
+
# Value: "," literal
|
|
120
|
+
# @example "," => Token(:comma, ",")
|
|
121
|
+
|
|
122
|
+
COMMA = :comma
|
|
123
|
+
|
|
124
|
+
# Dot separator in references (Schema.field)
|
|
125
|
+
# Value: "." literal
|
|
126
|
+
# @example "." => Token(:dot, ".")
|
|
127
|
+
|
|
128
|
+
DOT = :dot
|
|
129
|
+
|
|
130
|
+
# Minus sign for negative numbers
|
|
131
|
+
# Value: "-" literal
|
|
132
|
+
# @example "-" => Token(:minus, "-")
|
|
133
|
+
|
|
134
|
+
MINUS = :minus
|
|
135
|
+
|
|
136
|
+
# Arithmetic operators (used inside formula(...) expressions)
|
|
137
|
+
# @example "*" => Token(:star, "*")
|
|
138
|
+
STAR = :star
|
|
139
|
+
|
|
140
|
+
# @example "/" => Token(:slash, "/")
|
|
141
|
+
SLASH = :slash
|
|
142
|
+
|
|
143
|
+
# @example "+" => Token(:plus, "+")
|
|
144
|
+
PLUS = :plus
|
|
145
|
+
|
|
146
|
+
# ==========================================================================
|
|
147
|
+
|
|
148
|
+
# Value Tokens
|
|
149
|
+
# ==========================================================================
|
|
150
|
+
# These tokens represent literal values
|
|
151
|
+
|
|
152
|
+
# Numeric literal (integer or float)
|
|
153
|
+
# Value: Integer or Float
|
|
154
|
+
# @example "123" => Token(:number, 123)
|
|
155
|
+
# @example "3.14" => Token(:number, 3.14)
|
|
156
|
+
|
|
157
|
+
NUMBER = :number
|
|
158
|
+
|
|
159
|
+
# String literal (single or double quoted)
|
|
160
|
+
# Value: String (quotes stripped)
|
|
161
|
+
# @example '"hello"' => Token(:string, "hello")
|
|
162
|
+
|
|
163
|
+
STRING = :string
|
|
164
|
+
|
|
165
|
+
# Identifier (unquoted name, used in enums, etc.)
|
|
166
|
+
# Value: String
|
|
167
|
+
# @example "pending" => Token(:identifier, "pending")
|
|
168
|
+
|
|
169
|
+
IDENTIFIER = :identifier
|
|
170
|
+
|
|
171
|
+
# Range literal (min..max)
|
|
172
|
+
# Value: Range object
|
|
173
|
+
# @example "18..80" => Token(:range, 18..80)
|
|
174
|
+
|
|
175
|
+
RANGE = :range
|
|
176
|
+
|
|
177
|
+
# Percentage literal
|
|
178
|
+
# Value: Integer (percent without %)
|
|
179
|
+
# @example "50%" => Token(:percent, 50)
|
|
180
|
+
|
|
181
|
+
PERCENT = :percent
|
|
182
|
+
|
|
183
|
+
# ==========================================================================
|
|
184
|
+
|
|
185
|
+
# Keyword Tokens
|
|
186
|
+
# ==========================================================================
|
|
187
|
+
# These tokens represent reserved keywords
|
|
188
|
+
|
|
189
|
+
# Conditional keyword for field conditions
|
|
190
|
+
# Value: "if" literal
|
|
191
|
+
# @example "if" => Token(:if, "if")
|
|
192
|
+
|
|
193
|
+
IF = :if
|
|
194
|
+
|
|
195
|
+
# Boolean true keyword
|
|
196
|
+
# Value: true
|
|
197
|
+
# @example "true" => Token(:true, true)
|
|
198
|
+
|
|
199
|
+
TRUE_KW = :true
|
|
200
|
+
|
|
201
|
+
# Boolean false keyword
|
|
202
|
+
# Value: false
|
|
203
|
+
# @example "false" => Token(:false, false)
|
|
204
|
+
|
|
205
|
+
FALSE_KW = :false
|
|
206
|
+
|
|
207
|
+
# ==========================================================================
|
|
208
|
+
|
|
209
|
+
# Simulyra DSL Keywords
|
|
210
|
+
# ==========================================================================
|
|
211
|
+
# These tokens are specific to the Simulyra layered DSL structure
|
|
212
|
+
|
|
213
|
+
# Schema definition keyword
|
|
214
|
+
# Value: "schema" literal
|
|
215
|
+
# @example "schema User:" => Token(:schema_keyword, "schema")
|
|
216
|
+
|
|
217
|
+
SCHEMA_KEYWORD = :schema_keyword
|
|
218
|
+
|
|
219
|
+
# API definition keyword
|
|
220
|
+
# Value: "api" literal
|
|
221
|
+
# @example "api GET /users:" => Token(:api_keyword, "api")
|
|
222
|
+
|
|
223
|
+
API_KEYWORD = :api_keyword
|
|
224
|
+
|
|
225
|
+
# Scenario definition keyword
|
|
226
|
+
# Value: "scenario" literal
|
|
227
|
+
# @example "scenario Success:" => Token(:scenario_keyword, "scenario")
|
|
228
|
+
|
|
229
|
+
SCENARIO_KEYWORD = :scenario_keyword
|
|
230
|
+
|
|
231
|
+
# HTTP method token
|
|
232
|
+
# Value: Symbol (:get, :post, :put, :patch, :delete, :options, :head)
|
|
233
|
+
# @example "GET" => Token(:http_method, :get)
|
|
234
|
+
|
|
235
|
+
HTTP_METHOD = :http_method
|
|
236
|
+
|
|
237
|
+
# URL path token
|
|
238
|
+
# Value: String containing the path
|
|
239
|
+
# @example "/users/:id" => Token(:path, "/users/:id")
|
|
240
|
+
|
|
241
|
+
PATH = :path
|
|
242
|
+
|
|
243
|
+
# Schema reference token for explicit schema(:Name) syntax
|
|
244
|
+
# Value: String containing the schema name
|
|
245
|
+
# @example "schema(:User)" => Token(:schema_ref, "User")
|
|
246
|
+
|
|
247
|
+
SCHEMA_REF = :schema_ref
|
|
248
|
+
|
|
249
|
+
# ==========================================================================
|
|
250
|
+
|
|
251
|
+
# Behavior Tokens
|
|
252
|
+
# ==========================================================================
|
|
253
|
+
# These tokens represent behavior declarations
|
|
254
|
+
|
|
255
|
+
# Behavior annotation (@latency, @failure, etc.)
|
|
256
|
+
# Value: String containing behavior name without @
|
|
257
|
+
# @example "@latency" => Token(:at_behavior, "latency")
|
|
258
|
+
|
|
259
|
+
AT_BEHAVIOR = :at_behavior
|
|
260
|
+
|
|
261
|
+
# ==========================================================================
|
|
262
|
+
|
|
263
|
+
# Whitespace/Structure Tokens
|
|
264
|
+
# ==========================================================================
|
|
265
|
+
# These tokens represent structural elements based on whitespace
|
|
266
|
+
|
|
267
|
+
# Newline character
|
|
268
|
+
# Value: "\n" literal
|
|
269
|
+
# @example "\n" => Token(:newline, "\n")
|
|
270
|
+
|
|
271
|
+
NEWLINE = :newline
|
|
272
|
+
|
|
273
|
+
# Increase in indentation level
|
|
274
|
+
# Value: Integer (new indentation level)
|
|
275
|
+
# @example Indent from 0 to 2 => Token(:indent, 2)
|
|
276
|
+
|
|
277
|
+
INDENT = :indent
|
|
278
|
+
|
|
279
|
+
# Decrease in indentation level
|
|
280
|
+
# Value: Integer (new indentation level)
|
|
281
|
+
# @example Dedent from 4 to 2 => Token(:dedent, 2)
|
|
282
|
+
|
|
283
|
+
DEDENT = :dedent
|
|
284
|
+
|
|
285
|
+
# ==========================================================================
|
|
286
|
+
|
|
287
|
+
# Special Tokens
|
|
288
|
+
# ==========================================================================
|
|
289
|
+
# These tokens have special meaning
|
|
290
|
+
|
|
291
|
+
# End of file marker
|
|
292
|
+
# Value: nil
|
|
293
|
+
# @example End of input => Token(:eof, nil)
|
|
294
|
+
|
|
295
|
+
EOF = :eof
|
|
296
|
+
|
|
297
|
+
# Ruby symbol literal (:function_name)
|
|
298
|
+
# Value: Symbol
|
|
299
|
+
# @example ":compute" => Token(:symbol, :compute)
|
|
300
|
+
|
|
301
|
+
SYMBOL = :symbol
|
|
302
|
+
|
|
303
|
+
# ==========================================================================
|
|
304
|
+
|
|
305
|
+
# Token Type Collection
|
|
306
|
+
# ==========================================================================
|
|
307
|
+
|
|
308
|
+
# Array of all valid token types
|
|
309
|
+
#
|
|
310
|
+
# @return [Array<Symbol>] all token type symbols
|
|
311
|
+
#
|
|
312
|
+
# @example Validate token type
|
|
313
|
+
# Tokens::ALL.include?(token.type) # => true/false
|
|
314
|
+
#
|
|
315
|
+
|
|
316
|
+
ALL = [
|
|
317
|
+
SCHEMA_NAME, FIELD_NAME, COLON, QUESTION,
|
|
318
|
+
TYPE, REF,
|
|
319
|
+
LPAREN, RPAREN, COMMA, DOT, MINUS,
|
|
320
|
+
NUMBER, STRING, IDENTIFIER, RANGE, PERCENT,
|
|
321
|
+
IF, TRUE_KW, FALSE_KW,
|
|
322
|
+
SCHEMA_KEYWORD, API_KEYWORD, SCENARIO_KEYWORD, HTTP_METHOD, PATH, SCHEMA_REF,
|
|
323
|
+
AT_BEHAVIOR,
|
|
324
|
+
NEWLINE, INDENT, DEDENT,
|
|
325
|
+
EOF, SYMBOL
|
|
326
|
+
].freeze
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Represents a single token from the lexer
|
|
330
|
+
#
|
|
331
|
+
# A Token captures the type, value, and source location of a syntax
|
|
332
|
+
# element in the DSL. Tokens are produced by the Lexer and consumed
|
|
333
|
+
# by the Parser.
|
|
334
|
+
#
|
|
335
|
+
# @example Create a token
|
|
336
|
+
# token = Token.new(:type, "uuid", line: 5, column: 10)
|
|
337
|
+
# token.type # => :type
|
|
338
|
+
# token.value # => "uuid"
|
|
339
|
+
# token.line # => 5
|
|
340
|
+
# token.column # => 10
|
|
341
|
+
#
|
|
342
|
+
# @example Check token type
|
|
343
|
+
# token.type?(:type) # => true
|
|
344
|
+
# token.type?(:number) # => false
|
|
345
|
+
#
|
|
346
|
+
|
|
347
|
+
class Token
|
|
348
|
+
|
|
349
|
+
# @!attribute [r] type
|
|
350
|
+
# The token type (one of Tokens::ALL)
|
|
351
|
+
# @return [Symbol] the token type
|
|
352
|
+
|
|
353
|
+
attr_reader :type
|
|
354
|
+
|
|
355
|
+
# @!attribute [r] value
|
|
356
|
+
# The token value (varies by type)
|
|
357
|
+
# @return [Object] the token value
|
|
358
|
+
|
|
359
|
+
attr_reader :value
|
|
360
|
+
|
|
361
|
+
# @!attribute [r] line
|
|
362
|
+
# Source line number (1-based)
|
|
363
|
+
# @return [Integer] line number
|
|
364
|
+
|
|
365
|
+
attr_reader :line
|
|
366
|
+
|
|
367
|
+
# @!attribute [r] column
|
|
368
|
+
# Source column number (1-based)
|
|
369
|
+
# @return [Integer] column number
|
|
370
|
+
|
|
371
|
+
attr_reader :column
|
|
372
|
+
|
|
373
|
+
# Create a new Token
|
|
374
|
+
#
|
|
375
|
+
# @param type [Symbol] the token type (should be in Tokens::ALL)
|
|
376
|
+
# @param value [Object] the token value
|
|
377
|
+
# @param line [Integer] line number where token appears (1-based)
|
|
378
|
+
# @param column [Integer] column where token starts (1-based)
|
|
379
|
+
#
|
|
380
|
+
# @example
|
|
381
|
+
# Token.new(:number, 42, line: 3, column: 15)
|
|
382
|
+
#
|
|
383
|
+
|
|
384
|
+
def initialize(type, value, line:, column:)
|
|
385
|
+
@type = type
|
|
386
|
+
@value = value
|
|
387
|
+
@line = line
|
|
388
|
+
@column = column
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# String representation for debugging
|
|
392
|
+
#
|
|
393
|
+
# @return [String] human-readable token description
|
|
394
|
+
#
|
|
395
|
+
# @example
|
|
396
|
+
# token.to_s # => "Token(type, \"uuid\", line: 5, col: 10)"
|
|
397
|
+
#
|
|
398
|
+
|
|
399
|
+
def to_s
|
|
400
|
+
"Token(#{type}, #{value.inspect}, line: #{line}, col: #{column})"
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Inspect output (same as to_s)
|
|
404
|
+
#
|
|
405
|
+
# @return [String] inspect representation
|
|
406
|
+
#
|
|
407
|
+
|
|
408
|
+
def inspect
|
|
409
|
+
to_s
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# Check equality with another token
|
|
413
|
+
#
|
|
414
|
+
# Two tokens are equal if they have the same type and value.
|
|
415
|
+
# Line and column are not considered for equality.
|
|
416
|
+
#
|
|
417
|
+
# @param other [Token] token to compare
|
|
418
|
+
# @return [Boolean] true if type and value match
|
|
419
|
+
#
|
|
420
|
+
# @example
|
|
421
|
+
# token1 = Token.new(:type, "uuid", line: 1, column: 1)
|
|
422
|
+
# token2 = Token.new(:type, "uuid", line: 2, column: 5)
|
|
423
|
+
# token1 == token2 # => true (same type and value)
|
|
424
|
+
#
|
|
425
|
+
|
|
426
|
+
def ==(other)
|
|
427
|
+
return false unless other.is_a?(Token)
|
|
428
|
+
|
|
429
|
+
type == other.type && value == other.value
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Alias for == to support Hash key comparison
|
|
433
|
+
alias eql? ==
|
|
434
|
+
|
|
435
|
+
# Hash code for use in Hash keys and Sets
|
|
436
|
+
#
|
|
437
|
+
# Based on type and value only (not line/column).
|
|
438
|
+
#
|
|
439
|
+
# @return [Integer] hash code
|
|
440
|
+
#
|
|
441
|
+
|
|
442
|
+
def hash
|
|
443
|
+
[type, value].hash
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# Check if token is of a specific type
|
|
447
|
+
#
|
|
448
|
+
# @param expected_type [Symbol] type to check against
|
|
449
|
+
# @return [Boolean] true if token type matches
|
|
450
|
+
#
|
|
451
|
+
# @example
|
|
452
|
+
# token.type?(:type) # => true
|
|
453
|
+
# token.type?(:number) # => false
|
|
454
|
+
#
|
|
455
|
+
|
|
456
|
+
def type?(expected_type)
|
|
457
|
+
type == expected_type
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
end
|
|
461
|
+
end
|