forked from GaijinEntertainment/daScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial veresion of peg parser generator
- Loading branch information
Showing
8 changed files
with
1,429 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
IF(NOT DAS_PEG_INCLUDED) | ||
SET(DAS_PEG_INCLUDED TRUE) | ||
MESSAGE(STATUS "dasPEG module included.") | ||
|
||
ADD_MODULE_DAS(peg peg peg) | ||
ADD_MODULE_DAS(peg peg meta_ast) | ||
ADD_MODULE_DAS(peg peg parse_macro) | ||
ADD_MODULE_DAS(peg peg parser_generator) | ||
|
||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/modules/dasPEG/peg | ||
DESTINATION modules/dasPEG | ||
FILES_MATCHING | ||
PATTERN "*.das" | ||
) | ||
ENDIF() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
options indenting = 4 | ||
options no_unused_block_arguments = false | ||
options no_unused_function_arguments = false | ||
options no_aot = true | ||
options strict_smart_pointers = true | ||
|
||
// options log_infer_passes | ||
|
||
require strings | ||
require daslib/strings_boost | ||
|
||
require peg/peg | ||
|
||
|
||
// def match_string_literal(var parser: Parser): tuple<success:bool; string> | ||
// //! Tries to match everything inside "" | ||
|
||
// // Define buffer to store string literal characters | ||
// var inscope buffer: das_string | ||
|
||
// var current_char = parser |> get_current_char | ||
|
||
// // If the current character is not a double quote, the rule is not a string | ||
// return [[auto false, ""]] if current_char != '"' | ||
|
||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// while current_char != '"' && current_char != -1 | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// // If we've reached EOF file without finding a closing quote | ||
// return [[auto false, ""]] if current_char == -1 | ||
|
||
// parser |> move(1) | ||
// return [[auto true, buffer |> string()]] | ||
|
||
|
||
// def match_double_literal(var parser: Parser): tuple<success:bool; double> | ||
// //! Matches doubles in the form of [-+]? [0-9]* .? [0-9]+ ([eE] [-+]? [0-9]+)? | ||
// //! The number is not checked to be representable as defined in IEEE-754 | ||
|
||
// var inscope buffer: array<uint8> | ||
// var current_char = parser |> get_current_char | ||
|
||
// if current_char == '-' || current_char == '+' | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// // Add everything up to '.' to the buffer | ||
// while current_char |> is_number || current_char == '.' | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
|
||
// // Match exponent part | ||
// if current_char == 'e' || current_char == 'E' | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// // Check for '-' or '+' after 'e' or 'E' | ||
// if current_char == '-' || current_char == '+' | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// // Continue appending digits after 'e' or 'E' | ||
// while current_char |> is_number | ||
// buffer |> append(current_char) | ||
// parser |> move(1) | ||
// current_char = parser |> get_current_char | ||
|
||
// return [[auto true, buffer |> string() |> double()]] | ||
|
||
[export] | ||
def main | ||
|
||
var parser <- [[calcParser]] | ||
parser.input = "1+2*2+1---(3*2+1*2)-1-1-1*2" | ||
|
||
parse calc | ||
var add: int | ||
|
||
rule(add as a, "+", mul as m) <| | ||
return a + m | ||
rule(add as a, "-", mul as m) <| | ||
return a - m | ||
rule(mul as m) <| | ||
return m | ||
|
||
var mul: int | ||
|
||
rule(mul as m, "*", unary as u) <| | ||
return m * u | ||
rule(mul as m, "/", unary as u) <| | ||
return m / u | ||
rule(unary as u) <| | ||
return u | ||
|
||
var unary: int | ||
|
||
rule("-", unary as u) <| | ||
return u | ||
rule(prim as p) <| | ||
return p | ||
|
||
var prim: int | ||
|
||
rule("(", add as a, ")") <| | ||
return a | ||
rule(number as n) <| | ||
return n | ||
|
||
var res <- parser |> parse_add | ||
|
||
print("Assert {res.value} == -6\n") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
options indenting = 4 | ||
options no_unused_block_arguments = false | ||
options no_unused_function_arguments = false | ||
options no_aot = true | ||
options strict_smart_pointers = true | ||
|
||
require strings | ||
require daslib/strings_boost | ||
require daslib/json | ||
|
||
require peg/peg | ||
|
||
// Taken from daslib/json | ||
|
||
|
||
// struct JsonValue | ||
// //! JSON value, wraps any JSON element. | ||
// value : JsValue | ||
|
||
|
||
|
||
// variant JsValue | ||
// //! Single JSON element. | ||
// _object : table<string; JsonValue?> | ||
// _array : array<JsonValue?> | ||
// _string : string | ||
// _number : double | ||
// _bool : bool | ||
// _null : void? | ||
|
||
|
||
|
||
// Grammar: | ||
// | ||
// # A JSON text is a sequence of whitespace followed by an element | ||
// Json <- Spacing Element EOF | ||
// | ||
// # An element is an object, an array or a value | ||
// Element <- Object / Array / Value | ||
// | ||
// # A JSON object is an unordered set of name/value pairs | ||
// Object <- '{' Spacing Pair (',' Spacing Pair)* '}' Spacing | ||
// | ||
// Pair <- String ':' Spacing Element | ||
// | ||
// # A JSON array is an ordered collection of values | ||
// Array <- '[' Spacing Element (',' Spacing Element)* ']' Spacing | ||
// | ||
// # A JSON value can be a string, number, "true", "false", or "null" | ||
// Value <- String / Number / 'true' Spacing / 'false' Spacing / 'null' Spacing | ||
// | ||
// # JSON strings are surrounded by double quotes and support a backslash escaping syntax | ||
// String <- '"' (!'"' Character)* '"' Spacing | ||
// Character <- '\\' Escape / !'\\' . | ||
// | ||
// Escape <- ["\\/bfnrt] / 'u' [0-9A-Fa-f]{4} | ||
// | ||
|
||
|
||
// Creation helpers | ||
|
||
|
||
// def JV ( v : string ) | ||
// //! Creates `JsonValue` out of value. | ||
// return new [[JsonValue value <- [[JsValue _string = v]]]] | ||
|
||
// def JV ( v : double ) | ||
// return new [[JsonValue value <- [[JsValue _number = v]]]] | ||
|
||
// def JV ( v : bool ) | ||
// return new [[JsonValue value <- [[JsValue _bool = v]]]] | ||
|
||
// def JVNull | ||
// //! Creates `JsonValue` representing `null`. | ||
// return new [[JsonValue value <- [[JsValue _null = null]]]] | ||
|
||
// def JV ( var v : table<string;JsonValue?> ) | ||
// return new [[JsonValue value <- [[JsValue _object <- v]]]] | ||
|
||
// def JV ( var v : array<JsonValue?> ) | ||
// return new [[JsonValue value <- [[JsValue _array <- v]]]] | ||
|
||
|
||
def into_table(var src: array<tuple<auto(K); auto(V)>>): table<K; V> | ||
var result: table<K; V> | ||
for elem in src | ||
result[elem._0] <- elem._1 | ||
return <- result | ||
|
||
|
||
// Parsing specification | ||
|
||
|
||
[export] | ||
def main | ||
|
||
parse json | ||
var JsonValue: JsonValue? | ||
|
||
rule(WS, Element as e, EOF) <| | ||
return <- e | ||
|
||
|
||
|
||
var Element: JsonValue? | ||
|
||
rule(Array as a) <| | ||
print("Parsed element\n") | ||
return <- JV(a) | ||
|
||
// rule(Object as o) <| | ||
// return <- JV(o) | ||
|
||
rule(Value as v) <| | ||
return <- v | ||
|
||
|
||
|
||
|
||
|
||
var Array: array<JsonValue?> | ||
|
||
// Optional element list; | ||
// If items are present (not []), then no trailing comma is allowed | ||
|
||
rule("[", WS, MB(ElementList) as list, "]", WS) <| | ||
print("Parsed Array\n") | ||
return <- [[array<JsonValue?>]] if list |> empty | ||
print("List non empty\n") | ||
return <- list[0] // Take the value from optional | ||
|
||
|
||
var ElementList: array<JsonValue?> | ||
|
||
// Multiple (possibly none) comma-separated elements followed by the final one | ||
// If the list is not empty, there must always be a final one | ||
|
||
rule(*CommaSeparatedElements as els, Element as last) <| | ||
print("Parsed element list\n") | ||
els |> push <| last | ||
return <- els | ||
|
||
|
||
var CommaSeparatedElements: JsonValue? | ||
|
||
// Helper to shave off commas | ||
|
||
rule(Element as e, ",", WS) <| | ||
print("Parsed comma sep\n") | ||
return <- e | ||
|
||
|
||
|
||
|
||
// var Object: table<string; JsonValue?> | ||
|
||
// rule("\{", WS, MB(MappingList) as list, "\}", WS) <| | ||
// var empty: table<string; JsonValue?> | ||
// return <- empty if list |> empty | ||
// return <- list[0] |> into_table | ||
|
||
|
||
// var MappingList: array<tuple<string; JsonValue?>> | ||
|
||
// rule(*CommaSeparatedMappings as els, Mapping as last) <| | ||
// els |> push <| last | ||
// return <- els | ||
|
||
|
||
// var CommaSeparatedMappings: tuple<string; JsonValue?> | ||
|
||
// rule(Mapping as m, ",", WS) <| | ||
// return <- m | ||
|
||
|
||
// var Mapping: tuple<string; JsonValue?> | ||
|
||
// rule(string_ as s, WS, ":", WS, Element as e) <| | ||
// return <- [[tuple<string; JsonValue?> s, e]] | ||
|
||
|
||
|
||
|
||
|
||
|
||
var Value: JsonValue? | ||
|
||
rule("true", WS) <| | ||
print("Parsed true\n") | ||
return <- JV(true) | ||
|
||
rule("false", WS) <| | ||
return <- JV(false) | ||
|
||
rule("null", WS) <| | ||
return <- JVNull() | ||
|
||
// rule(double_ as d, WS) <| // <- builtin double_ rule | ||
// return <- JV(d) | ||
|
||
rule(string_ as s, WS) <| // <- builtin string_ rule | ||
print("Parsed sring\n") | ||
return <- JV(s) | ||
|
||
|
||
|
||
var parser <- [[jsonParser]] | ||
parser.input = "[\"123\", true,[], [[true]], \"123\"]" | ||
|
||
var result <- parser |> parse_JsonValue() | ||
|
||
var r <- parser |> parse_JsonValue() | ||
|
||
print ("{result.value |> write_json}\n") | ||
|
||
return |
Oops, something went wrong.