aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Coquand <marc@mccd.space>2023-12-26 10:08:23 -0600
committerMarc Coquand <marc@mccd.space>2023-12-26 10:08:23 -0600
commitd96e1839eb800bf26bcc38272072d98af69f5d83 (patch)
tree1570f7f47ba4e39acf4caebfce6eaf4a6575bc97
parent2bb4215b957d912058d490c16ee64320e3724037 (diff)
downloadfixgen-d96e1839eb800bf26bcc38272072d98af69f5d83.tar.gz
fixgen-d96e1839eb800bf26bcc38272072d98af69f5d83.tar.bz2
fixgen-d96e1839eb800bf26bcc38272072d98af69f5d83.zip
Support const keyword
-rw-r--r--lib/ast_types.ml5
-rw-r--r--lib/fixture.ml5
-rw-r--r--lib/lexer.mll18
-rw-r--r--lib/parser.mly7
-rw-r--r--test/test_parser.ml1
5 files changed, 34 insertions, 2 deletions
diff --git a/lib/ast_types.ml b/lib/ast_types.ml
index b9f4294..c278d59 100644
--- a/lib/ast_types.ml
+++ b/lib/ast_types.ml
@@ -5,6 +5,7 @@ type ast_row =
| Uuidv4 of string * ast_row
| Name of string * ast_row
| Int of string * int * int * ast_row
+ | Const of string * string * ast_row
| Foreign of string * string * string * ast_row
(* parent, row, child_name, row *)
| End
@@ -19,6 +20,9 @@ let rec print_row = function
| Uuidv4 (s, r) ->
printf "UUIDv4(%s)," s;
print_row r
+ | Const (s, v, r) ->
+ printf "Const(%s, %s)," s v;
+ print_row r
| Foreign (p, r, c, next_row) ->
printf "Foreign(%s.%s, %s)," p r c;
print_row next_row
@@ -60,6 +64,7 @@ let rec ast_row_to_fixtures = function
CRow (p, r, fun l -> Fixture.Foreign (c, l)) :: ast_row_to_fixtures next_row
| Name (s, r) -> PRow (Fixture.Name s) :: ast_row_to_fixtures r
| Int (s, min, max, r) -> PRow (Fixture.Int (s, min, max)) :: ast_row_to_fixtures r
+ | Const (s, v, r) -> PRow (Fixture.Const (s, v)) :: ast_row_to_fixtures r
| End -> []
diff --git a/lib/fixture.ml b/lib/fixture.ml
index 25f6a8f..2b17a02 100644
--- a/lib/fixture.ml
+++ b/lib/fixture.ml
@@ -22,12 +22,12 @@ let names =
let random_name () = List.nth names (Random.int (List.length names))
let%test "random_name" = List.mem (random_name ()) names
-(* TODO: Support names *)
type t =
| Name of string
| Uuidv4 of string
| Foreign of (string * string list)
| Int of string * int * int
+ | Const of string * string
(* (Name, foreign ids to pick from) *)
let add_name name fixtures = Name name :: fixtures
@@ -46,6 +46,7 @@ let generate_fixture fixture =
| Name _ -> random_name ()
| Uuidv4 _ -> Uuidm.v `V4 |> Uuidm.to_string
| Foreign (_, reference) -> random_value_in_list reference
+ | Const (_, value) -> value
| Int (_, min, max) -> Random.int (max - min) + min |> string_of_int
@@ -58,10 +59,10 @@ let id_of_fixture fixture =
| Name id -> id
| Uuidv4 id -> id
| Foreign (id, _) -> id
+ | Const (id, _) -> id
| Int (id, _, _) -> id
-(* TODO: Support const *)
(* TODO: Support email *)
(* TODO: Support list *)
diff --git a/lib/lexer.mll b/lib/lexer.mll
index e0c5453..6e9b975 100644
--- a/lib/lexer.mll
+++ b/lib/lexer.mll
@@ -23,6 +23,7 @@ rule read =
| "_int" { INTSYMBOL }
| "(" { LBRACE }
| ")" { RBRACE }
+ | '"' { read_string (Buffer.create 20) lexbuf }
| int { INT (Lexing.lexeme lexbuf |> int_of_string) }
| white { read lexbuf }
| ":" { COLON }
@@ -32,3 +33,20 @@ rule read =
| "." { DOT }
| eof { EOF }
| _ as c { failwith (Printf.sprintf "unexpected character: %C" c) }
+
+and read_string buf =
+ parse
+ | '"' { STRING (Buffer.contents buf) }
+ | '\\' '/' { Buffer.add_char buf '/'; read_string buf lexbuf }
+ | '\\' '\\' { Buffer.add_char buf '\\'; read_string buf lexbuf }
+ | '\\' 'b' { Buffer.add_char buf '\b'; read_string buf lexbuf }
+ | '\\' 'f' { Buffer.add_char buf '\012'; read_string buf lexbuf }
+ | '\\' 'n' { Buffer.add_char buf '\n'; read_string buf lexbuf }
+ | '\\' 'r' { Buffer.add_char buf '\r'; read_string buf lexbuf }
+ | '\\' 't' { Buffer.add_char buf '\t'; read_string buf lexbuf }
+ | [^ '"' '\\']+
+ { Buffer.add_string buf (Lexing.lexeme lexbuf);
+ read_string buf lexbuf
+ }
+ | _ { raise (SyntaxError ("Illegal string character: " ^ Lexing.lexeme lexbuf)) }
+ | eof { raise (SyntaxError ("String is not terminated")) }
diff --git a/lib/parser.mly b/lib/parser.mly
index e9d06bc..6e21480 100644
--- a/lib/parser.mly
+++ b/lib/parser.mly
@@ -14,6 +14,7 @@
%token <int> INT
%token LBRACE
%token RBRACE
+%token <string> STRING
%start <ast_table option > prog
%%
@@ -30,10 +31,16 @@ expr:
row:
| row_title = IDENTIFIER; parent = IDENTIFIER; DOT; parent_id = IDENTIFIER; COMMA; r = row { Foreign (parent,parent_id,row_title, r) }
| row_title = IDENTIFIER; parent = IDENTIFIER; DOT; parent_id = IDENTIFIER; { Foreign (parent,parent_id,row_title, End) }
+
| row_title = IDENTIFIER; UUIDV4; COMMA; r = row { Uuidv4 (row_title, r) }
| row_title = IDENTIFIER; UUIDV4 { Uuidv4 (row_title, End) }
+
| row_title = IDENTIFIER; NAME; COMMA; r = row { Name (row_title, r) }
| row_title = IDENTIFIER; NAME { Name (row_title, End) }
+
+ | row_title = IDENTIFIER; const = STRING; COMMA; r = row { Const (row_title, const, r) }
+ | row_title = IDENTIFIER; const = STRING { Const (row_title, const, End) }
+
| row_title = IDENTIFIER; INTSYMBOL;LBRACE;min = INT;COMMA;max = INT;RBRACE;COMMA; r = row { Int (row_title,min,max,r) }
| row_title = IDENTIFIER; INTSYMBOL;LBRACE;min = INT;COMMA;max = INT;RBRACE; { Int (row_title,min,max,End) }
;
diff --git a/test/test_parser.ml b/test/test_parser.ml
index 5a56e6a..abb0a40 100644
--- a/test/test_parser.ml
+++ b/test/test_parser.ml
@@ -18,6 +18,7 @@ let rows_suite =
, `Quick
, test_parse "user (1): id _uuidv4\npurchases (1): id _uuidv4" )
; "Supports names", `Quick, test_parse "purchases (1): name _name"
+ ; "Supports const", `Quick, test_parse "purchases (1): name \"hello\""
; "Supports ints with min/max", `Quick, test_parse "purchases (1): name _int(1,20)"
; ( "Supports setting amount of fixture to generate"
, `Quick