Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix loc #299

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# v2.0.5 (December 2024)


Requires Menhir 20211230 and OCaml 4.13 or above.

- Parser:
- Fix loc issues involving quotations

# v2.0.4 (November 2024)


Expand Down
66 changes: 33 additions & 33 deletions src/parser/lexer.mll.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
open Elpi_lexer_config.Tokens
exception Error of string

let real_skip b n =
let open Lexing in
b.lex_curr_p <- { b.lex_curr_p with pos_cnum = b.lex_curr_p.pos_cnum + n };
b.lex_start_p <- { b.lex_start_p with pos_cnum = b.lex_start_p.pos_cnum + n }

let new_line b =
Lexing.new_line b

let skip b n =
let open Lexing in
b.lex_curr_p <- { b.lex_curr_p with pos_cnum = b.lex_curr_p.pos_cnum + n }

let start_token f b =
let open Lexing in
let start = b.lex_start_pos in
Expand Down Expand Up @@ -68,65 +69,64 @@ let symbcharplus = symbchar +
rule linecomment = parse
| '\n' { new_line lexbuf; token lexbuf }
| eof { token lexbuf }
| "elpi:skip " (pnum as n) { skip lexbuf 10; skip lexbuf (String.length n); linecomment_skip (int_of_string n) lexbuf }
| "elpi:if" (' '+ as sp1) "version" (' '+ as sp2) (['<' '>' '='] as op) (' '+ as sp3) (pnum as ma) "." (pnum as mi) "." (pnum as p) {
skip lexbuf (7+7+1); skip lexbuf String.(length ma + length mi + length p + length sp1 + length sp2 + length sp3);
| "elpi:skip " (pnum as n) { linecomment_skip (int_of_string n) lexbuf }
| "elpi:if" (' '+) "version" (' '+) (['<' '>' '='] as op) (' '+) (pnum as ma) "." (pnum as mi) "." (pnum as p) {
if not @@ version_test op ma mi p then linecomment_if lexbuf else linecomment_drop lexbuf }
| ' ' { skip lexbuf 1; linecomment lexbuf }
| _ { skip lexbuf 1; linecomment_drop lexbuf }
| ' ' { linecomment lexbuf }
| _ { linecomment_drop lexbuf }

and linecomment_drop = parse
| '\n' { new_line lexbuf; token lexbuf }
| eof { token lexbuf }
| _ { skip lexbuf 1; linecomment_drop lexbuf }
| _ { linecomment_drop lexbuf }

and linecomment_skip skipno = parse
| '\n' { new_line lexbuf; if skipno > 0 then skip_lines skipno lexbuf else token lexbuf }
| eof { token lexbuf }
| _ { skip lexbuf 1; linecomment_skip skipno lexbuf }
| _ { linecomment_skip skipno lexbuf }

and linecomment_if = parse
| '\n' { new_line lexbuf; skip_lines_endif lexbuf }
| eof { token lexbuf }
| _ { skip lexbuf 1; linecomment_if lexbuf }
| _ { linecomment_if lexbuf }

and skip_lines_endif = parse
| '\n' { new_line lexbuf; skip_lines_endif lexbuf }
| '%' (' '+ as sp) "elpi:endif" { skip lexbuf (1 + (String.length sp) + 10); token lexbuf }
| '%' (' '+) "elpi:endif" { token lexbuf }
| eof { token lexbuf }
| _ { skip lexbuf 1; skip_lines_endif lexbuf }
| _ { skip_lines_endif lexbuf }

and skip_lines skipno = parse
| '\n' { new_line lexbuf; let skipno = skipno - 1 in if skipno > 0 then skip_lines skipno lexbuf else token lexbuf }
| eof { token lexbuf }
| _ { skip lexbuf 1; skip_lines skipno lexbuf }
| _ { skip_lines skipno lexbuf }

and multilinecomment nest = parse
| '\n' { new_line lexbuf; multilinecomment nest lexbuf }
| "*/" { if nest = 0 then token lexbuf else multilinecomment (nest - 1) lexbuf }
| "/*" { multilinecomment (nest+1) lexbuf }
| _ { skip lexbuf 1; multilinecomment nest lexbuf }
| _ { multilinecomment nest lexbuf }

and string b = parse
| '\n' { Buffer.add_char b '\n'; new_line lexbuf; string b lexbuf }
| '\\' 'n' { Buffer.add_char b '\n'; skip lexbuf 2; string b lexbuf }
| '\\' 'b' { Buffer.add_char b '\b'; skip lexbuf 2; string b lexbuf }
| '\\' 't' { Buffer.add_char b '\t'; skip lexbuf 2; string b lexbuf }
| '\\' 'r' { Buffer.add_char b '\r'; skip lexbuf 2; string b lexbuf }
| '\\' '\\' { Buffer.add_char b '\\'; skip lexbuf 2; string b lexbuf }
| '\\' '"' { Buffer.add_char b '"'; skip lexbuf 2; string b lexbuf }
| '"' '"' { Buffer.add_char b '"'; skip lexbuf 2; string b lexbuf }
| '\\' 'n' { Buffer.add_char b '\n'; string b lexbuf }
| '\\' 'b' { Buffer.add_char b '\b'; string b lexbuf }
| '\\' 't' { Buffer.add_char b '\t'; string b lexbuf }
| '\\' 'r' { Buffer.add_char b '\r'; string b lexbuf }
| '\\' '\\' { Buffer.add_char b '\\'; string b lexbuf }
| '\\' '"' { Buffer.add_char b '"'; string b lexbuf }
| '"' '"' { Buffer.add_char b '"'; string b lexbuf }
| '"' { STRING (Buffer.contents b) }
| _ # '"' as c { Buffer.add_char b c; skip lexbuf 1; string b lexbuf }
| _ # '"' as c { Buffer.add_char b c; string b lexbuf }

and quoted n = parse
| '{' { skip lexbuf 1; quoted (n+1) lexbuf }
| '\n' { let b = Buffer.create 80 in Buffer.add_char b '\n'; skip lexbuf 1; new_line lexbuf; quoted_inner b n 0 lexbuf }
| _ as c { let b = Buffer.create 80 in Buffer.add_char b c; skip lexbuf 1; quoted_inner b n 0 lexbuf }
| '{' { quoted (n+1) lexbuf }
| '\n' { let b = Buffer.create 80 in Buffer.add_char b '\n'; new_line lexbuf; quoted_inner b n 0 lexbuf }
| _ as c { let b = Buffer.create 80 in Buffer.add_char b c; quoted_inner b n 0 lexbuf }

and quoted_inner b n l = parse
| '}' {
Buffer.add_char b '}'; skip lexbuf 1;
Buffer.add_char b '}';
try lookahead_close b (n-1) lexbuf;
if l = 0 then begin
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_cnum = lexbuf.lex_curr_p.pos_cnum - 1};
Expand All @@ -136,7 +136,7 @@ and quoted_inner b n l = parse
with Failure _ -> quoted_inner b n l lexbuf
}
| '{' {
Buffer.add_char b '{'; skip lexbuf 1;
Buffer.add_char b '{';
try lookahead_open b (n-1) lexbuf; quoted_inner b n (l+1) lexbuf
with Failure _ -> quoted_inner b n l lexbuf
}
Expand All @@ -145,13 +145,13 @@ and quoted_inner b n l = parse

and lookahead_close b n = parse
| '}' {
Buffer.add_char b '}'; skip lexbuf 1;
Buffer.add_char b '}'; real_skip lexbuf 1;
if n = 1 then () else lookahead_close b (n-1) lexbuf
}

and lookahead_open b n = parse
| '{' {
Buffer.add_char b '{'; skip lexbuf 1;
Buffer.add_char b '{'; real_skip lexbuf 1;
if n = 1 then () else lookahead_open b (n-1) lexbuf
}

Expand All @@ -167,7 +167,7 @@ and token = parse
lexbuf.lex_abs_pos <- - (String.length x) - lexbuf.lex_start_p.pos_cnum;
lexbuf.lex_start_p <- lexbuf.lex_curr_p;
token lexbuf }
| ( ' ' | '\t' | '\r' ) { skip lexbuf 1; token lexbuf }
| ( ' ' | '\t' | '\r' ) { token lexbuf }
| '\n' { new_line lexbuf; token lexbuf }
| '%' { linecomment lexbuf }
| "/*" { multilinecomment 0 lexbuf }
Expand All @@ -189,7 +189,7 @@ and token = parse
| "{" { LCURLY }
| "}" { RCURLY }
| "|" { PIPE }
| "{{" { start_token (fun b -> skip b 2; quoted 2 b) lexbuf }
| "{{" { start_token (fun b -> quoted 2 b) lexbuf }
| (("i" | "o") as s) ':' { IO_COLON s }
| ("i" | "o") as s { IO s }
| "shorten" { SHORTEN }
Expand Down
2 changes: 1 addition & 1 deletion src/parser/parse.ml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ let lexing_set_position lexbuf loc =
let open Lexing in
lexbuf.lex_abs_pos <- loc.pos_cnum;
lexbuf.lex_start_p <- loc;
lexbuf.lex_curr_p <- { loc with pos_cnum = loc.pos_cnum + 1 }
lexbuf.lex_curr_p <- loc

let goal_from ~loc lexbuf =
lexing_set_position lexbuf loc;
Expand Down
146 changes: 80 additions & 66 deletions src/parser/test_lexer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,14 @@ let error s n msg =
Printf.eprintf "lexing '%s' at char %d: %s\n" s n msg;
exit 1

let validate s (tok1,lnum1,bol1,cnum1) (tok2,lnum2, bol2, cnum2) =
let validate s (tok1,lnum1,bol1,bnum1,cnum1) (tok2,lnum2, bol2, bnum2,cnum2) =
if tok1 <> tok2 then error s cnum2 (Printf.sprintf "wrong token: got %s instead of %s" (show tok2) (show tok1));
if lnum1 <> lnum2 then error s cnum2 (Printf.sprintf "wrong line number: got %d instead of %d" lnum2 lnum1);
if bol1 <> bol2 then error s cnum2 (Printf.sprintf "wrong begin of line: got %d instead of %d" bol2 bol1);
if cnum1 <> cnum2 then error s cnum2 (Printf.sprintf "wrong char count: got %d instead of %d" cnum2 cnum1)
if bnum1 <> bnum2 then error s bnum2 (Printf.sprintf "wrong char begin count: got %d instead of %d" bnum2 bnum1);
if cnum1 <> cnum2 then error s cnum2 (Printf.sprintf "wrong char end count: got %d instead of %d" cnum2 cnum1);
if bol1 <> bol2 then error s cnum2 (Printf.sprintf "wrong begin of line: got %d instead of %d" bol2 bol1)

type exp = T of t * int * int * int | E
type exp = T of t * int * int * int * int | E

let rec expect s b = function
| [] -> ()
Expand All @@ -114,95 +115,108 @@ let rec expect s b = function
let tok2 = Lexer.token b in
let open Lexing in
let p = b.lex_curr_p in
let lnum2, bol2, cnum2 = p.pos_lnum, p.pos_bol, p.pos_cnum in
let lnum2, bol2, bnum2, cnum2 = p.pos_lnum, p.pos_bol, b.lex_start_p.pos_cnum, p.pos_cnum in
match sp with
| T (tok1,lnum1,bol1,cnum1) -> validate s (tok1,lnum1,bol1,cnum1) (tok2,lnum2, bol2, cnum2)
| T (tok1,lnum1,bol1,bnum1,cnum1) -> validate s (tok1,lnum1,bol1,bnum1,cnum1) (tok2,lnum2, bol2, bnum2, cnum2)
| E -> error s cnum2 (Printf.sprintf "wrong lexing: got %s instead of error" (show tok2))
with Failure _ ->
match sp with
| E -> ()
| T (tok1,_,_,cnum1) -> error s cnum1 (Printf.sprintf "wrong lexing: got error instead of %s" (show tok1))
| T (tok1,_,_,_,cnum1) -> error s cnum1 (Printf.sprintf "wrong lexing: got error instead of %s" (show tok1))
end;
expect s b spec

let test s spec =
let s = Str.global_replace (Str.regexp_string "\r") "" s in
let b = Lexing.from_string s in
Printf.eprintf "=============================\n";
expect s b spec

let () =

(* 01234567890123456789012345 *)
test "3.4" [T(FLOAT 3.4, 1, 0, 3)];
test " 3.4" [T(FLOAT 3.4, 1, 0, 4)];
test "\n3.4" [T(FLOAT 3.4, 2, 1, 4)];
test "3.4 .5" [T(FLOAT 3.4, 1, 0, 3); T(FLOAT 0.5, 1, 0, 6)];
test "3.4\n .5" [T(FLOAT 3.4, 1, 0, 3); T(FLOAT 0.5, 2, 4, 7)];
test "3.4" [T(FLOAT 3.4, 1, 0, 0, 3)];
test " 3.4" [T(FLOAT 3.4, 1, 0, 1, 4)];
test "\n3.4" [T(FLOAT 3.4, 2, 1, 1, 4)];
test "3.4 .5" [T(FLOAT 3.4, 1, 0, 0, 3); T(FLOAT 0.5, 1, 0, 4, 6)];
test "3.4\n .5" [T(FLOAT 3.4, 1, 0, 0, 3); T(FLOAT 0.5, 2, 4, 5, 7)];
(* 01234567890123456789012345 *)
test "3 .4" [T(INTEGER 3, 1, 0, 1); T(FLOAT 0.4, 1, 0, 4)];
test "3..4" [T(INTEGER 3, 1, 0, 1); T(FULLSTOP, 1, 0, 2); T(FLOAT 0.4, 1, 0, 4)];
test "3." [T(INTEGER 3, 1, 0, 1); T(FULLSTOP, 1, 0, 2)];
test "-3." [T(INTEGER (-3), 1, 0, 2); T(FULLSTOP, 1, 0, 3)];
test "3 .4" [T(INTEGER 3, 1, 0, 0, 1); T(FLOAT 0.4, 1, 0, 2, 4)];
test "3..4" [T(INTEGER 3, 1, 0, 0, 1); T(FULLSTOP, 1, 0, 1, 2); T(FLOAT 0.4, 1, 0, 2, 4)];
test "3." [T(INTEGER 3, 1, 0, 0, 1); T(FULLSTOP, 1, 0, 1, 2)];
test "-3." [T(INTEGER (-3), 1, 0, 0, 2); T(FULLSTOP, 1, 0, 2, 3)];
(* 01234567890123456789012345 *)
test "3%...\n3" [T(INTEGER 3, 1, 0, 1); T(INTEGER 3, 2, 6, 7)];
test "3/*..*/3" [T(INTEGER 3, 1, 0, 1); T(INTEGER 3, 1, 0, 8)];
test "3/** T **/3" [T(INTEGER 3, 1, 0, 1); T(INTEGER 3, 1, 0, 11)];
test "3/*\n.*/3" [T(INTEGER 3, 1, 0, 1); T(INTEGER 3, 2, 4, 8)];
test "3/*\n/*\n*/*/3" [T(INTEGER 3, 1, 0, 1); T(INTEGER 3, 3, 7, 12)];
test "3/*" [T(INTEGER 3, 1, 0, 1); E];
test "3%...\n3" [T(INTEGER 3, 1, 0, 0, 1); T(INTEGER 3, 2, 6, 6, 7)];
test "3/*..*/3" [T(INTEGER 3, 1, 0, 0, 1); T(INTEGER 3, 1, 0, 7, 8)];
test "3/** T **/3" [T(INTEGER 3, 1, 0, 0, 1); T(INTEGER 3, 1, 0, 10, 11)];
test "3/*\n.*/3" [T(INTEGER 3, 1, 0, 0, 1); T(INTEGER 3, 2, 4, 7, 8)];
test "3/*\n/*\n*/*/3" [T(INTEGER 3, 1, 0, 0, 1); T(INTEGER 3, 3, 7, 11, 12)];
test "3/*" [T(INTEGER 3, 1, 0, 0, 1); E];
(* 01234567890123456789012345 *)
test {|"a"|} [T(STRING "a", 1, 0, 3)];
test {|"a""b"|} [T(STRING "a\"b", 1, 0, 6)];
test {|"a\nb"|} [T(STRING "a\nb", 1, 0, 6)];
test {|"a"|} [T(STRING "a", 1, 0, 0, 3)];
test {|"a""b"|} [T(STRING "a\"b", 1, 0, 0, 6)];
test {|"a\nb"|} [T(STRING "a\nb", 1, 0, 0, 6)];
test {|"a
b"|} [T(STRING "a\nb", 2, 3, 5)];
b"|} [T(STRING "a\nb", 2, 3, 0, 5)];
(* 01234567890123456789012345 *)
test "x" [T(CONSTANT "x", 1, 0, 0, 1)];
test " x" [T(CONSTANT "x", 1, 0, 1, 2)];
test "xx" [T(CONSTANT "xx", 1, 0, 0, 2)];
test " xx" [T(CONSTANT "xx", 1, 0, 1, 3)];

test "x-y" [T(CONSTANT "x-y", 1, 0, 0,3)];
test "-y" [T(MINUS, 1, 0, 0,1); T(CONSTANT "y",1,0,1,2)];
test "_y" [T(CONSTANT "_y", 1, 0, 0,2)];
test "_X" [T(CONSTANT "_X", 1, 0, 0,2)];
test "X_" [T(CONSTANT "X_", 1, 0, 0,2)];
test "x?" [T(CONSTANT "x?", 1, 0, 0,2)];
test "X" [T(CONSTANT "X", 1, 0, 0,1)];
test "X1>@!" [T(CONSTANT "X1>@!", 1, 0, 0,5)];
test "a.B.c" [T(CONSTANT "a.B.c", 1, 0, 0,5)];
test "a.B." [T(CONSTANT "a.B", 1, 0, 0,3); T(FULLSTOP, 1, 0, 3, 4)];
test "a. >" [T(CONSTANT "a", 1, 0, 0,1); T(FULLSTOP, 1, 0, 1, 2); T(FAMILY_GT ">", 1, 0, 3,4)];
(* 01234567890123456789012345 *)
test "x" [T(CONSTANT "x", 1, 0, 1)];
test "x-y" [T(CONSTANT "x-y", 1, 0, 3)];
test "-y" [T(MINUS, 1, 0, 1); T(CONSTANT "y",1,0,2)];
test "_y" [T(CONSTANT "_y", 1, 0, 2)];
test "_X" [T(CONSTANT "_X", 1, 0, 2)];
test "X_" [T(CONSTANT "X_", 1, 0, 2)];
test "x?" [T(CONSTANT "x?", 1, 0, 2)];
test "X" [T(CONSTANT "X", 1, 0, 1)];
test "X1>@!" [T(CONSTANT "X1>@!", 1, 0, 5)];
test "a.B.c" [T(CONSTANT "a.B.c", 1, 0, 5)];
test "a.B." [T(CONSTANT "a.B", 1, 0, 3); T(FULLSTOP, 1, 0, 4)];
test "a. >" [T(CONSTANT "a", 1, 0, 1); T(FULLSTOP, 1, 0, 2); T(FAMILY_GT ">", 1, 0, 4)];
test "-->" [T(FAMILY_MINUS "-->", 1, 0, 0,3)];
test "x.y->z" [T(CONSTANT "x.y->z", 1, 0, 0,6)];
(* 01234567890123456789012345 *)
test "-->" [T(FAMILY_MINUS "-->", 1, 0, 3)];
test "x.y->z" [T(CONSTANT "x.y->z", 1, 0, 6)];
test "{{{ }} }}}" [T(QUOTED (3," }} "), 1, 0, 0,10)];
test "{{ {{ } }} }}" [T(QUOTED (2," {{ } }} "), 1, 0, 0,13)];

(* 01234567890123456789012345 *)
test "{{{ }} }}}" [T(QUOTED (3," }} "), 1, 0, 10)];
test "{{ {{ } }} }}" [T(QUOTED (2," {{ } }} "), 1, 0, 13)];
test "{{ x }}3" [T(QUOTED (2," x "), 1, 0, 7); T(INTEGER 3, 1, 0, 8)];
test "{{{ x }}}3" [T(QUOTED (3," x "), 1, 0, 9); T(INTEGER 3, 1, 0, 10)];
test "{{\n x }}3" [T(QUOTED (2,"\n x "), 2, 4, 8); T(INTEGER 3, 2, 4, 9)];
test "{{ x }}3" [T(QUOTED (2," x "), 1, 0, 0, 7); T(INTEGER 3, 1, 0, 7, 8)];
test "2{{ x }}" [T(INTEGER 2, 1, 0, 0, 1); T(QUOTED (2," x "), 1, 0, 1, 8)];
test "2 {{ x }}" [T(INTEGER 2, 1, 0, 0, 1); T(QUOTED (2," x "), 1, 0, 2, 9)];
test "{{{ x }}}3" [T(QUOTED (3," x "), 1, 0, 0, 9); T(INTEGER 3, 1, 0, 9, 10)];
test "{{\n x }}3" [T(QUOTED (2,"\n x "), 2, 3, 0, 8); T(INTEGER 3, 2, 3, 8, 9)];

(* 01234567890123456789012345 *)
test "foo :- bar." [T(CONSTANT "foo", 1, 0, 3); T(VDASH, 1, 0, 6); T(CONSTANT "bar", 1, 0, 10); T(FULLSTOP, 1, 0, 11)];
test "foo ?- bar." [T(CONSTANT "foo", 1, 0, 3); T(QDASH, 1, 0, 6); T(CONSTANT "bar", 1, 0, 10); T(FULLSTOP, 1, 0, 11)];
test "foo :- x \\ bar." [T(CONSTANT "foo", 1, 0, 3); T(VDASH, 1, 0, 6); T(CONSTANT "x", 1, 0, 8); T(BIND, 1, 0, 10); T(CONSTANT "bar", 1, 0, 14); T(FULLSTOP, 1, 0, 15)];
test "foo, bar" [T(CONSTANT "foo", 1, 0, 3); T(CONJ, 1, 0, 4); T(CONSTANT "bar", 1, 0, 8) ];
test "foo & bar" [T(CONSTANT "foo", 1, 0, 3); T(CONJ2, 1, 0, 5); T(CONSTANT "bar", 1, 0, 9) ];
test "[]" [T(LBRACKET, 1, 0, 1); T(RBRACKET, 1, 0, 2)];
test "foo :- bar." [T(CONSTANT "foo", 1, 0, 0,3); T(VDASH, 1, 0, 4,6); T(CONSTANT "bar", 1, 0, 7,10); T(FULLSTOP, 1, 0, 10,11)];
test "foo ?- bar." [T(CONSTANT "foo", 1, 0, 0,3); T(QDASH, 1, 0, 4,6); T(CONSTANT "bar", 1, 0, 7,10); T(FULLSTOP, 1, 0, 10,11)];
test "foo :- x \\ bar." [T(CONSTANT "foo", 1, 0, 0,3); T(VDASH, 1, 0, 4,6); T(CONSTANT "x", 1, 0, 7,8); T(BIND, 1, 0, 9,10); T(CONSTANT "bar", 1, 0, 11,14); T(FULLSTOP, 1, 0, 14,15)];
test "foo, bar" [T(CONSTANT "foo", 1, 0, 0,3); T(CONJ, 1, 0, 3,4); T(CONSTANT "bar", 1, 0, 5,8) ];
test "foo & bar" [T(CONSTANT "foo", 1, 0, 0,3); T(CONJ2, 1, 0, 4,5); T(CONSTANT "bar", 1, 0, 6,9) ];
test "[]" [T(LBRACKET, 1, 0, 0,1); T(RBRACKET, 1, 0, 1,2)];
(* 01234567890123456789012345 *)
test "X" [T(CONSTANT "X", 1, 0, 1) ];
test "is" [T(IS, 1, 0, 2) ];
test "#line 3 \"xx\"\na" [T(CONSTANT "a", 3, 0, 1) ];
test "b\n#line 3 \"xx\"\na" [T(CONSTANT "b", 1, 0, 1);T(CONSTANT "a", 3, 2, 1) ];
test "X" [T(CONSTANT "X", 1, 0, 0,1) ];
test "is" [T(IS, 1, 0, 0,2) ];
test "#line 3 \"xx\"\na" [T(CONSTANT "a", 3, 0, 0,1) ];
test "b\n#line 3 \"xx\"\na" [T(CONSTANT "b", 1, 0, 0,1);T(CONSTANT "a", 3, 2, 0,1) ];
test {|
b
c
#line 7 "xx"
a|} [T(CONSTANT "b", 2, 1, 2);T(CONSTANT "c", 3, 3, 4);T(CONSTANT "a", 7, 5, 1) ];
a|} [T(CONSTANT "b", 2, 1, 1,2);T(CONSTANT "c", 3, 3, 3,4);T(CONSTANT "a", 7, 5, 0,1) ];

(* 01234567890123456789012345 *)
test ":name" [T(COLON,1,0,1); T(NAME,1,0,5)];
test "@foo" [T(CONSTANT "@foo",1,0,4)];
test "a && b" [T(CONSTANT "a",1,0,1);T(FAMILY_AND "&&",1,0,4);T(CONSTANT "b",1,0,6)];
test ":name" [T(COLON,1,0,0,1); T(NAME,1,0,1,5)];
test "@foo" [T(CONSTANT "@foo",1,0,0,4)];
test "a && b" [T(CONSTANT "a",1,0,0,1);T(FAMILY_AND "&&",1,0,2,4);T(CONSTANT "b",1,0,5,6)];

(* 01234567890123456789012345 *)
test "i:" [T(IO_COLON 'i', 1, 0, 2)];
test "o:" [T(IO_COLON 'o', 1, 0, 2)];
test "i :" [T(IO 'i', 1, 0, 1); T(COLON,1,0,3)];
test "o :" [T(IO 'o', 1, 0, 1); T(COLON,1,0,3)];
test "i" [T(IO 'i', 1, 0, 1)];
test "o" [T(IO 'o', 1, 0, 1)];
test "func" [T(FUNC, 1, 0, 4)];
test "i:" [T(IO_COLON 'i', 1, 0, 0,2)];
test "o:" [T(IO_COLON 'o', 1, 0, 0,2)];
test "i :" [T(IO 'i', 1, 0, 0,1); T(COLON,1,0,2,3)];
test "o :" [T(IO 'o', 1, 0, 0,1); T(COLON,1,0,2,3)];
test "i" [T(IO 'i', 1, 0, 0,1)];
test "o" [T(IO 'o', 1, 0, 0,1)];
test "func" [T(FUNC, 1, 0, 0,4)];
Loading
Loading