From 1107a5cf2a684033a212663311f8a383da91f2e8 Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Wed, 16 Oct 2013 00:44:59 -0400 Subject: [PATCH] nitcc: introduce nitcc Signed-off-by: Jean Privat --- contrib/nitcc/.gitignore | 16 + contrib/nitcc/autom.nit | 541 ++++++++++ contrib/nitcc/examples/calc.nit | 82 ++ contrib/nitcc/examples/calc.sablecc | 22 + contrib/nitcc/examples/json.sablecc | 31 + contrib/nitcc/examples/minilang.minilang | 28 + contrib/nitcc/examples/minilang.nit | 182 ++++ contrib/nitcc/examples/minilang.sablecc | 57 ++ contrib/nitcc/examples/mkml.sh | 5 + contrib/nitcc/grammar.nit | 1054 ++++++++++++++++++++ contrib/nitcc/mk | 33 + contrib/nitcc/nitcc.nit | 147 +++ contrib/nitcc/nitcc.sablecc | 95 ++ contrib/nitcc/nitcc_lexer0.nit | 163 +++ contrib/nitcc/nitcc_parser_gen.nit | 150 +++ contrib/nitcc/nitcc_runtime.nit | 543 ++++++++++ contrib/nitcc/nitcc_semantic.nit | 487 +++++++++ contrib/nitcc/re2nfa.nit | 153 +++ contrib/nitcc/t/alterner.pl | 186 ++++ contrib/nitcc/t/empty.input | 1 + contrib/nitcc/t/empty.sablecc | 15 + contrib/nitcc/t/if.sablecc | 15 + contrib/nitcc/t/inf5000-04-lexer-automate.input | 9 + contrib/nitcc/t/inf5000-04-lexer-automate.sablecc | 14 + contrib/nitcc/t/inf5000-04-lexer-demo.input | 3 + contrib/nitcc/t/inf5000-04-lexer-demo.input2 | 1 + contrib/nitcc/t/inf5000-04-lexer-demo.sablecc | 14 + contrib/nitcc/t/inf5000-04-lexer-pire_cout.input | 1 + contrib/nitcc/t/inf5000-04-lexer-pire_cout.input2 | 1 + contrib/nitcc/t/inf5000-04-lexer-pire_cout.sablecc | 9 + .../t/inf5000-04-lexer-priorite_d_inclusion.input | 3 + .../inf5000-04-lexer-priorite_d_inclusion.sablecc | 9 + .../t/inf5000-04-lexer-priorite_declaree.input | 4 + .../t/inf5000-04-lexer-priorite_declaree.sablecc | 11 + .../t/inf5000-05-grammaire-arithmetique.input | 5 + .../t/inf5000-05-grammaire-arithmetique.sablecc | 18 + .../t/inf5000-05-grammaire-arithmetique2.input | 5 + .../t/inf5000-05-grammaire-arithmetique2.sablecc | 17 + contrib/nitcc/t/inf5000-05-grammaire-formes.input | 1 + .../nitcc/t/inf5000-05-grammaire-formes.sablecc | 12 + contrib/nitcc/t/inf5000-05-grammaire-lisp.input | 1 + contrib/nitcc/t/inf5000-05-grammaire-lisp.sablecc | 13 + contrib/nitcc/t/inf5000-05-grammaire-listes.input | 1 + .../nitcc/t/inf5000-05-grammaire-listes.sablecc | 10 + .../nitcc/t/inf5000-05-grammaire-parentheses.input | 1 + .../t/inf5000-05-grammaire-parentheses.sablecc | 9 + .../t/inf5000-06-grammaire2-calculatrice.input | 1 + .../t/inf5000-06-grammaire2-calculatrice.sablecc | 15 + .../nitcc/t/inf5000-06-grammaire2-grammaire.input | 6 + .../t/inf5000-06-grammaire2-grammaire.sablecc | 15 + .../nitcc/t/inf5000-06-grammaire2-grammaire2.input | 6 + .../t/inf5000-06-grammaire2-grammaire2.sablecc | 13 + .../t/inf5000-06-grammaire2-instructions.input | 2 + .../t/inf5000-06-grammaire2-instructions.sablecc | 22 + .../nitcc/t/inf5000-06-grammaire2-polygone.input | 1 + .../nitcc/t/inf5000-06-grammaire2-polygone.sablecc | 11 + contrib/nitcc/t/lalr.sablecc | 5 + contrib/nitcc/t/lexer-c-comment.sablecc | 19 + contrib/nitcc/t/lexer-errors.sablecc | 15 + .../t/lexer-implicit-longest-and-priority.input | 1 + .../t/lexer-implicit-longest-and-priority.sablecc | 10 + contrib/nitcc/t/lexer-implicit-longest.input | 1 + contrib/nitcc/t/lexer-implicit-longest.sablecc | 8 + contrib/nitcc/t/lexer-markers.input | 1 + contrib/nitcc/t/lexer-markers.sablecc | 10 + contrib/nitcc/t/lexer-precedences.input | 1 + contrib/nitcc/t/lexer-precedences.sablecc | 14 + contrib/nitcc/t/lexer-shortest-longest.input | 1 + contrib/nitcc/t/lexer-shortest-longest.sablecc | 20 + contrib/nitcc/t/lexer-shortest-longest2.input | 1 + contrib/nitcc/t/lexer-shortest-longest2.sablecc | 12 + contrib/nitcc/t/lexer_conflict_token.sablecc | 10 + contrib/nitcc/t/lexer_empty_token.sablecc | 10 + contrib/nitcc/t/lexer_features.input | 5 + contrib/nitcc/t/lexer_features.input2 | 1 + contrib/nitcc/t/lr1.sablecc | 5 + contrib/nitcc/t/modif.input1 | 1 + contrib/nitcc/t/modif.input2 | 1 + contrib/nitcc/t/modif.input3 | 1 + contrib/nitcc/t/modif.input4 | 1 + contrib/nitcc/t/modif.sablecc | 8 + contrib/nitcc/t/nit_expr.sablecc | 11 + contrib/nitcc/t/not_lalr.sablecc | 5 + contrib/nitcc/t/not_slr.sablecc | 7 + contrib/nitcc/t/pri.sablecc | 7 + contrib/nitcc/t/priority.sablecc | 7 + contrib/nitcc/t/qualified.sablecc | 8 + contrib/nitcc/t/run | 1 + contrib/nitcc/t/sav/empty.alt1.res | 2 + contrib/nitcc/t/sav/empty.alt2.res | 1 + contrib/nitcc/t/sav/empty.alt3.input.res | 1 + contrib/nitcc/t/sav/empty.alt3.input2.res | 1 + contrib/nitcc/t/sav/empty.alt3.res | 1 + contrib/nitcc/t/sav/empty.alt4.res | 1 + contrib/nitcc/t/sav/empty.alt5.input.res | 2 + contrib/nitcc/t/sav/empty.alt5.input2.res | 1 + contrib/nitcc/t/sav/empty.alt5.res | 1 + contrib/nitcc/t/sav/empty.alt6.input.res | 2 + contrib/nitcc/t/sav/empty.alt6.input2.res | 1 + contrib/nitcc/t/sav/empty.alt6.res | 1 + contrib/nitcc/t/sav/empty.input.res | 2 + contrib/nitcc/t/sav/empty.input2.res | 2 + .../t/sav/inf5000-04-lexer-automate.input.res | 46 + .../nitcc/t/sav/inf5000-04-lexer-demo.input.res | 22 + .../nitcc/t/sav/inf5000-04-lexer-demo.input2.res | 3 + .../t/sav/inf5000-04-lexer-pire_cout.input.res | 6 + .../t/sav/inf5000-04-lexer-pire_cout.input2.res | 68 ++ ...inf5000-04-lexer-priorite_d_inclusion.input.res | 12 + .../inf5000-04-lexer-priorite_declaree.input.res | 6 + .../t/sav/inf5000-04-lexer-priorite_declaree.res | 2 + .../sav/inf5000-05-grammaire-arithmetique.alt1.res | 2 + .../inf5000-05-grammaire-arithmetique.input.res | 60 ++ .../t/sav/inf5000-05-grammaire-arithmetique.res | 1 + .../inf5000-05-grammaire-arithmetique2.input.res | 81 ++ .../t/sav/inf5000-05-grammaire-formes.input.res | 21 + .../t/sav/inf5000-05-grammaire-lisp.input.res | 39 + .../t/sav/inf5000-05-grammaire-listes.input.res | 8 + .../sav/inf5000-05-grammaire-parentheses.input.res | 11 + .../inf5000-06-grammaire2-calculatrice.input.res | 12 + .../t/sav/inf5000-06-grammaire2-calculatrice.res | 2 + .../sav/inf5000-06-grammaire2-grammaire.input.res | 109 ++ .../sav/inf5000-06-grammaire2-grammaire2.input.res | 41 + .../t/sav/inf5000-06-grammaire2-grammaire2.res | 2 + ...f5000-06-grammaire2-instructions.alt1.input.res | 32 + ...f5000-06-grammaire2-instructions.alt2.input.res | 32 + ...f5000-06-grammaire2-instructions.alt3.input.res | 18 + .../inf5000-06-grammaire2-instructions.alt3.res | 2 + .../inf5000-06-grammaire2-instructions.input.res | 32 + .../t/sav/inf5000-06-grammaire2-polygone.input.res | 10 + .../nitcc/t/sav/inf5000-06-grammaire2-polygone.res | 2 + contrib/nitcc/t/sav/lexer-c-comment.alt1.res | 2 + contrib/nitcc/t/sav/lexer-c-comment.alt2.res | 1 + contrib/nitcc/t/sav/lexer-c-comment.alt3.res | 2 + contrib/nitcc/t/sav/lexer-c-comment.alt4.res | 2 + contrib/nitcc/t/sav/lexer-c-comment.res | 1 + contrib/nitcc/t/sav/lexer-errors.alt1.res | 1 + contrib/nitcc/t/sav/lexer-errors.alt3.res | 1 + contrib/nitcc/t/sav/lexer-errors.alt4.res | 1 + contrib/nitcc/t/sav/lexer-errors.alt5.res | 1 + contrib/nitcc/t/sav/lexer-errors.alt7.res | 2 + contrib/nitcc/t/sav/lexer-errors.alt8.res | 1 + contrib/nitcc/t/sav/lexer-errors.res | 1 + ...er-implicit-longest-and-priority.alt1.input.res | 5 + .../lexer-implicit-longest-and-priority.alt1.res | 2 + .../t/sav/lexer-implicit-longest-and-priority.res | 2 + .../t/sav/lexer-implicit-longest.alt1.input.res | 4 + .../nitcc/t/sav/lexer-implicit-longest.alt1.res | 2 + contrib/nitcc/t/sav/lexer-implicit-longest.res | 2 + contrib/nitcc/t/sav/lexer-markers.alt1.input.res | 4 + contrib/nitcc/t/sav/lexer-markers.alt2.input.res | 4 + contrib/nitcc/t/sav/lexer-markers.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt1.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt10.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt2.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt3.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt4.input.res | 4 + contrib/nitcc/t/sav/lexer-precedences.alt4.res | 1 + .../nitcc/t/sav/lexer-precedences.alt5.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt6.input.res | 4 + .../nitcc/t/sav/lexer-precedences.alt7.input.res | 4 + contrib/nitcc/t/sav/lexer-precedences.alt8.res | 2 + .../nitcc/t/sav/lexer-precedences.alt9.input.res | 4 + contrib/nitcc/t/sav/lexer-precedences.res | 1 + .../nitcc/t/sav/lexer-shortest-longest.alt1.res | 2 + .../nitcc/t/sav/lexer-shortest-longest.alt2.res | 2 + .../nitcc/t/sav/lexer-shortest-longest.alt3.res | 2 + .../nitcc/t/sav/lexer-shortest-longest.input.res | 5 + contrib/nitcc/t/sav/lexer-shortest-longest.res | 2 + .../t/sav/lexer-shortest-longest2.alt1.input.res | 3 + .../nitcc/t/sav/lexer-shortest-longest2.alt1.res | 2 + .../nitcc/t/sav/lexer-shortest-longest2.alt2.res | 2 + .../t/sav/lexer-shortest-longest2.alt3.input.res | 3 + .../nitcc/t/sav/lexer-shortest-longest2.alt3.res | 2 + .../nitcc/t/sav/lexer-shortest-longest2.alt4.res | 2 + contrib/nitcc/t/sav/lexer-shortest-longest2.res | 2 + contrib/nitcc/t/sav/lexer_conflict_token.res | 1 + contrib/nitcc/t/sav/lexer_empty_token.res | 1 + contrib/nitcc/t/sav/lexer_features.input.res | 9 + contrib/nitcc/t/sav/lexer_features.input2.res | 2 + contrib/nitcc/t/sav/lr1.res | 1 + contrib/nitcc/t/sav/modif.input1.res | 5 + contrib/nitcc/t/sav/modif.input2.res | 25 + contrib/nitcc/t/sav/modif.input3.res | 4 + contrib/nitcc/t/sav/modif.input4.res | 7 + contrib/nitcc/t/sav/nit_expr.res | 1 + contrib/nitcc/t/sav/not_lalr.res | 1 + contrib/nitcc/t/sav/pri.res | 1 + contrib/nitcc/t/sav/priority.res | 1 + contrib/nitcc/t/sav/qualified.res | 1 + contrib/nitcc/t/sav/trans.input.res | 7 + contrib/nitcc/t/sav/trans_inline.input.res | 7 + contrib/nitcc/t/t | 139 +++ contrib/nitcc/t/trans.sablecc | 7 + contrib/nitcc/t/trans_inline.sablecc | 6 + 194 files changed, 5519 insertions(+) create mode 100644 contrib/nitcc/.gitignore create mode 100644 contrib/nitcc/autom.nit create mode 100644 contrib/nitcc/examples/calc.nit create mode 100644 contrib/nitcc/examples/calc.sablecc create mode 100644 contrib/nitcc/examples/json.sablecc create mode 100644 contrib/nitcc/examples/minilang.minilang create mode 100644 contrib/nitcc/examples/minilang.nit create mode 100644 contrib/nitcc/examples/minilang.sablecc create mode 100755 contrib/nitcc/examples/mkml.sh create mode 100644 contrib/nitcc/grammar.nit create mode 100755 contrib/nitcc/mk create mode 100644 contrib/nitcc/nitcc.nit create mode 100644 contrib/nitcc/nitcc.sablecc create mode 100644 contrib/nitcc/nitcc_lexer0.nit create mode 100644 contrib/nitcc/nitcc_parser_gen.nit create mode 100644 contrib/nitcc/nitcc_runtime.nit create mode 100644 contrib/nitcc/nitcc_semantic.nit create mode 100644 contrib/nitcc/re2nfa.nit create mode 100755 contrib/nitcc/t/alterner.pl create mode 100644 contrib/nitcc/t/empty.input create mode 100644 contrib/nitcc/t/empty.input2 create mode 100644 contrib/nitcc/t/empty.sablecc create mode 100644 contrib/nitcc/t/if.sablecc create mode 100644 contrib/nitcc/t/inf5000-04-lexer-automate.input create mode 100644 contrib/nitcc/t/inf5000-04-lexer-automate.sablecc create mode 100644 contrib/nitcc/t/inf5000-04-lexer-demo.input create mode 100644 contrib/nitcc/t/inf5000-04-lexer-demo.input2 create mode 100644 contrib/nitcc/t/inf5000-04-lexer-demo.sablecc create mode 100644 contrib/nitcc/t/inf5000-04-lexer-pire_cout.input create mode 100644 contrib/nitcc/t/inf5000-04-lexer-pire_cout.input2 create mode 100644 contrib/nitcc/t/inf5000-04-lexer-pire_cout.sablecc create mode 100644 contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.input create mode 100644 contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.sablecc create mode 100644 contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.input create mode 100644 contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-arithmetique.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-arithmetique.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-formes.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-formes.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-lisp.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-lisp.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-listes.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-listes.sablecc create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-parentheses.input create mode 100644 contrib/nitcc/t/inf5000-05-grammaire-parentheses.sablecc create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.input create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.sablecc create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-grammaire.input create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-grammaire.sablecc create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.input create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.sablecc create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-instructions.input create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-instructions.sablecc create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-polygone.input create mode 100644 contrib/nitcc/t/inf5000-06-grammaire2-polygone.sablecc create mode 100644 contrib/nitcc/t/lalr.sablecc create mode 100644 contrib/nitcc/t/lexer-c-comment.sablecc create mode 100644 contrib/nitcc/t/lexer-errors.sablecc create mode 100644 contrib/nitcc/t/lexer-implicit-longest-and-priority.input create mode 100644 contrib/nitcc/t/lexer-implicit-longest-and-priority.sablecc create mode 100644 contrib/nitcc/t/lexer-implicit-longest.input create mode 100644 contrib/nitcc/t/lexer-implicit-longest.sablecc create mode 100644 contrib/nitcc/t/lexer-markers.input create mode 100644 contrib/nitcc/t/lexer-markers.sablecc create mode 100644 contrib/nitcc/t/lexer-precedences.input create mode 100644 contrib/nitcc/t/lexer-precedences.sablecc create mode 100644 contrib/nitcc/t/lexer-shortest-longest.input create mode 100644 contrib/nitcc/t/lexer-shortest-longest.sablecc create mode 100644 contrib/nitcc/t/lexer-shortest-longest2.input create mode 100644 contrib/nitcc/t/lexer-shortest-longest2.sablecc create mode 100644 contrib/nitcc/t/lexer_conflict_token.sablecc create mode 100644 contrib/nitcc/t/lexer_empty_token.sablecc create mode 100644 contrib/nitcc/t/lexer_features.input create mode 100644 contrib/nitcc/t/lexer_features.input2 create mode 100644 contrib/nitcc/t/lr1.sablecc create mode 100644 contrib/nitcc/t/modif.input1 create mode 100644 contrib/nitcc/t/modif.input2 create mode 100644 contrib/nitcc/t/modif.input3 create mode 100644 contrib/nitcc/t/modif.input4 create mode 100644 contrib/nitcc/t/modif.sablecc create mode 100644 contrib/nitcc/t/nit_expr.sablecc create mode 100644 contrib/nitcc/t/not_lalr.sablecc create mode 100644 contrib/nitcc/t/not_slr.sablecc create mode 100644 contrib/nitcc/t/pri.sablecc create mode 100644 contrib/nitcc/t/priority.sablecc create mode 100644 contrib/nitcc/t/qualified.sablecc create mode 100755 contrib/nitcc/t/run create mode 100644 contrib/nitcc/t/sav/calc.res create mode 100644 contrib/nitcc/t/sav/empty.alt1.res create mode 100644 contrib/nitcc/t/sav/empty.alt2.res create mode 100644 contrib/nitcc/t/sav/empty.alt3.input.res create mode 100644 contrib/nitcc/t/sav/empty.alt3.input2.res create mode 100644 contrib/nitcc/t/sav/empty.alt3.res create mode 100644 contrib/nitcc/t/sav/empty.alt4.res create mode 100644 contrib/nitcc/t/sav/empty.alt5.input.res create mode 100644 contrib/nitcc/t/sav/empty.alt5.input2.res create mode 100644 contrib/nitcc/t/sav/empty.alt5.res create mode 100644 contrib/nitcc/t/sav/empty.alt6.input.res create mode 100644 contrib/nitcc/t/sav/empty.alt6.input2.res create mode 100644 contrib/nitcc/t/sav/empty.alt6.res create mode 100644 contrib/nitcc/t/sav/empty.input.res create mode 100644 contrib/nitcc/t/sav/empty.input2.res create mode 100644 contrib/nitcc/t/sav/empty.res create mode 100644 contrib/nitcc/t/sav/expression.res create mode 100644 contrib/nitcc/t/sav/if.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-automate.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-automate.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-demo.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-demo.input2.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-demo.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input2.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.alt1.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-formes.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-formes.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-listes.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-listes.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.input.res create mode 100644 contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.res create mode 100644 contrib/nitcc/t/sav/json.res create mode 100644 contrib/nitcc/t/sav/lalr.res create mode 100644 contrib/nitcc/t/sav/lexer-c-comment.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-c-comment.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-c-comment.alt3.res create mode 100644 contrib/nitcc/t/sav/lexer-c-comment.alt4.res create mode 100644 contrib/nitcc/t/sav/lexer-c-comment.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt3.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt4.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt5.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt6.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt7.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.alt8.res create mode 100644 contrib/nitcc/t/sav/lexer-errors.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.input.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest.alt1.input.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-implicit-longest.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.alt1.input.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.alt2.input.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.input.res create mode 100644 contrib/nitcc/t/sav/lexer-markers.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt1.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt10.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt10.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt2.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt3.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt3.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt4.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt4.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt5.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt5.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt6.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt6.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt7.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt7.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt8.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt9.input.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.alt9.res create mode 100644 contrib/nitcc/t/sav/lexer-precedences.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest.alt3.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest.input.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.input.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt2.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.input.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.alt4.res create mode 100644 contrib/nitcc/t/sav/lexer-shortest-longest2.res create mode 100644 contrib/nitcc/t/sav/lexer_conflict_token.res create mode 100644 contrib/nitcc/t/sav/lexer_empty_token.res create mode 100644 contrib/nitcc/t/sav/lexer_features.input.res create mode 100644 contrib/nitcc/t/sav/lexer_features.input2.res create mode 100644 contrib/nitcc/t/sav/lexer_features.res create mode 100644 contrib/nitcc/t/sav/lr1.res create mode 100644 contrib/nitcc/t/sav/minilang.res create mode 100644 contrib/nitcc/t/sav/mixed_list.res create mode 100644 contrib/nitcc/t/sav/modif.input1.res create mode 100644 contrib/nitcc/t/sav/modif.input2.res create mode 100644 contrib/nitcc/t/sav/modif.input3.res create mode 100644 contrib/nitcc/t/sav/modif.input4.res create mode 100644 contrib/nitcc/t/sav/modif.res create mode 100644 contrib/nitcc/t/sav/nit_expr.res create mode 100644 contrib/nitcc/t/sav/not_lalr.res create mode 100644 contrib/nitcc/t/sav/not_slr.res create mode 100644 contrib/nitcc/t/sav/pri.res create mode 100644 contrib/nitcc/t/sav/priority.res create mode 100644 contrib/nitcc/t/sav/qualified.res create mode 100644 contrib/nitcc/t/sav/trans.input.res create mode 100644 contrib/nitcc/t/sav/trans.res create mode 100644 contrib/nitcc/t/sav/trans_inline.input.res create mode 100644 contrib/nitcc/t/sav/trans_inline.res create mode 100755 contrib/nitcc/t/t create mode 100644 contrib/nitcc/t/trans.sablecc create mode 100644 contrib/nitcc/t/trans_inline.sablecc diff --git a/contrib/nitcc/.gitignore b/contrib/nitcc/.gitignore new file mode 100644 index 0000000..6e56095 --- /dev/null +++ b/contrib/nitcc/.gitignore @@ -0,0 +1,16 @@ +*.dot +*_parser.nit +*_lexer.nit +*_test_parser +*.concrete_grammar.txt +*.lr.txt +t/alt +t/out +t/tap.output + +nitcc_parser_gen +nitcc0 +nitcc1 +nitcc +examples/calc +examples/minilang diff --git a/contrib/nitcc/autom.nit b/contrib/nitcc/autom.nit new file mode 100644 index 0000000..2d1ca78 --- /dev/null +++ b/contrib/nitcc/autom.nit @@ -0,0 +1,541 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Finite automaton (NFA & DFA) +module autom + +# For the class Token +import grammar + +# A finite automaton +class Automaton + # The start state + var start: State + + # State that are accect states + var accept = new Array[State] + + # All states + var states = new Array[State] + + # Tokens associated on accept states + # use `add_tag` to update + var tags = new HashMap[State, Set[Token]] + + # Accept states associated on tokens + # use `add_tag` to update + var retrotags = new HashMap[Token, Set[State]] + + # Add a token to a state + fun add_tag(s: State, t: Token) + do + if not tags.has_key(s) then + var set = new ArraySet[Token] + tags[s] = set + set.add t + else + tags[s].add t + end + + if not retrotags.has_key(t) then + var set = new ArraySet[State] + retrotags[t] = set + set.add s + else + retrotags[t].add s + end + end + + # Remove tokens from conflicting state according the the inclusion of language + # REQUIRE: self isa DFA automaton + fun solve_token_inclusion + do + for s, ts in tags do + if ts.length <= 1 then continue + var losers = new Array[Token] + for t1 in ts do + for t2 in ts do + if t1 == t2 then continue + if retrotags[t1].length > retrotags[t2].length and retrotags[t1].has_all(retrotags[t2]) then + losers.add(t1) + break + end + end + end + for t in losers do + ts.remove(t) + retrotags[t].remove s + end + end + end + + # Initialize a new automaton for the empty language + # one state, no accept, no transition + init empty + do + var state = new State + start = state + states.add state + end + + # Initialize a new automaton for the empty-string language + # one state, is accept, no transition + init epsilon + do + var state = new State + start = state + accept.add state + states.add state + end + + # Initialize a new automation for the language that accepts only a single symbol + # Two state, the second is accept, one transition on `symbol` + init atom(symbol: Int) + do + var s = new State + var a = new State + s.add_trans(a, symbol) + start = s + accept.add a + states.add s + states.add a + end + + # Initialize a new automation for the language that accepts only a range of symbols + # Two state, the second is accept, one transition for `from` to `to` + init cla(from, to: Int) + do + var s = new State + var a = new State + for symbol in [from..to] do + s.add_trans(a, symbol) + end + start = s + accept.add a + states.add s + states.add a + end + + # Contatenate `other` to `self` + # other is modified and invalidated. + fun concat(other: Automaton) + do + var s2 = other.start + for a1 in accept do + a1.add_trans(s2, null) + end + accept = other.accept + states.add_all other.states + end + + # `self` become the alternation of `self` and `other` + # `other` is modified and invalidated. + fun alternate(other: Automaton) + do + var s = new State + var a = new State + s.add_trans(start, null) + for a1 in accept do + a1.add_trans(a, null) + end + s.add_trans(other.start, null) + for a2 in other.accept do + a2.add_trans(a, null) + accept.add(a2) + end + + start = s + accept = [a] + + states.add s + states.add a + states.add_all other.states + end + + # Do the Kleene closure (*) on self + fun close + do + for a1 in accept do + a1.add_trans(start, null) + start.add_trans(a1, null) + end + end + + # Do the + on self + fun plus + do + for a1 in accept do + a1.add_trans(start, null) + end + end + + # Do the ? on self + fun optionnal + do + alternate(new Automaton.epsilon) + end + + # Remove all transitions on a given symbol + fun minus_sym(symbol: Int) + do + for s in states do + for t in s.outs.to_a do + if t.symbol == symbol then t.delete + end + end + end + + # Fully duplicate an automaton + fun dup: Automaton + do + var res = new Automaton.empty + var map = new HashMap[State, State] + map[start] = res.start + for s in states do + if s == start then continue + var s2 = new State + map[s] = s2 + res.states.add(s2) + end + for s in accept do + res.accept.add map[s] + end + for s, ts in tags do for t in ts do + res.add_tag(map[s], t) + end + for s in states do + for t in s.outs do + map[s].add_trans(map[t.to], t.symbol) + end + end + return res + end + + # Produce a graphvis file for the automaton + fun to_dot(filepath: String) + do + var f = new OFStream.open(filepath) + f.write("digraph g \{\n") + + for s in states do + f.write("s{s.object_id}[") + #f.write("label=\"\",") + if accept.has(s) then + f.write("color=blue") + if tags.has_key(s) then + f.write(",label=\"") + for token in tags[s] do + f.write("{token.name.escape_to_c}\\n") + end + f.write("\"") + end + end + f.write("];\n") + var outs = new HashMap[State, Array[nullable Int]] + for t in s.outs do + var a + var s2 = t.to + var c = t.symbol + if outs.has_key(s2) then + a = outs[s2] + else + a = new Array[nullable Int] + outs[s2] = a + end + a.add(c) + end + for s2, a in outs do + var labe = "" + var lastc: nullable Int = null + var elip = 0 + a.add(-1) + for c in a do + if c == null then + if not labe.is_empty then labe += "\n" + labe += "''" + else if lastc == c - 1 then + elip += 1 + lastc = c + else + if elip == 1 then + assert lastc != null + labe += "\n{sym_to_s(lastc)}" + else if elip > 1 then + assert lastc != null + labe += " .. {sym_to_s(lastc)}" + end + if c == -1 then break + if not labe.is_empty then labe += "\n" + labe += sym_to_s(c) + lastc = c + end + end + f.write("s{s.object_id}->s{s2.object_id} [label=\"{labe.escape_to_c}\"];\n") + end + end + f.write("empty->s{start.object_id}; empty[label=\"\",shape=none];\n") + + f.write("\}\n") + f.close + end + + # Transform a symbol to a string + # Used by `to_dot` + private fun sym_to_s(symbol: nullable Int): String + do + if symbol == null then + return "''" + else if symbol <= 32 then + return "#{symbol}" + else + return symbol.ascii.to_s + end + end + + # Transform a NFA to a DFA + # note: the DFA is not miminized + fun to_dfa: Automaton + do + var dfa = new Automaton.empty + var n2d = new ArrayMap[Set[State], State] + var seen = new ArraySet[Set[State]] + var ts = new HashSet[Int] + var st = eclosure([start]) + var todo = [st] + n2d[st] = dfa.start + seen.add(st) + while not todo.is_empty do + var nfa_states = todo.pop + #print "* work on {nfa_states.inspect}={nfa_states} (remains {todo.length}/{seen.length})" + var dfa_state = n2d[nfa_states] + ts.clear + for s in nfa_states do + if accept.has(s) then + if tags.has_key(s) then + for t in tags[s] do + dfa.add_tag(dfa_state, t) + end + end + dfa.accept.add(dfa_state) + end + for t in s.outs do + var sym = t.symbol + if sym == null or ts.has(sym) then continue + ts.add(sym) + var nfa_dest = eclosure(trans(nfa_states, sym)) + #print "{nfa_states} -> {sym} -> {nfa_dest}" + var dfa_dest + if seen.has(nfa_dest) then + #print "* reuse {nfa_dest.inspect}={nfa_dest}" + dfa_dest = n2d[nfa_dest] + else + #print "* new {nfa_dest.inspect}={nfa_dest}" + dfa_dest = new State + dfa.states.add(dfa_dest) + n2d[nfa_dest] = dfa_dest + todo.add(nfa_dest) + seen.add(nfa_dest) + end + dfa_state.add_trans(dfa_dest, sym) + end + end + end + return dfa + end + + # epsilon-closure on a state of states + # used by `to_dfa` + private fun eclosure(states: Collection[State]): Set[State] + do + var res = new ArraySet[State] + res.add_all(states) + var todo = states.to_a + while not todo.is_empty do + var s = todo.pop + for t in s.outs do + if t.symbol != null then continue + var to = t.to + if res.has(to) then continue + res.add(to) + todo.add(to) + end + end + return res + end + + # trans on a set of states + # Used by `to_dfa` + fun trans(states: Collection[State], symbol: Int): Set[State] + do + var res = new ArraySet[State] + for s in states do + for t in s.outs do + if t.symbol != symbol then continue + var to = t.to + if res.has(to) then continue + res.add(to) + end + end + return res + end + + # Generate the Nit source code of the lexer + # `filepath` is the name of the ouptit file + # `parser` is the name of the parser module (used to import the token classes) + fun gen_to_nit(filepath: String, parser: nullable String) + do + var gen = new DFAGenerator(filepath, self, parser) + gen.gen_to_nit + end +end + +# Generate the Nit source code of the lexer +private class DFAGenerator + var filepath: String + var automaton: Automaton + var parser: nullable String + + var out: OStream + init(filepath: String, automaton: Automaton, parser: nullable String) do + self.filepath = filepath + self.automaton = automaton + self.parser = parser + self.out = new OFStream.open(filepath) + end + + fun add(s: String) do out.write(s) + + fun gen_to_nit + do + var names = new HashMap[State, String] + var i = 0 + for s in automaton.states do + names[s] = i.to_s + i += 1 + end + + add "# Lexer generated by nitcc" + add("import nitcc_runtime\n") + + var p = parser + if p != null then add("import {p}\n") + + add("class MyLexer\n") + add("\tsuper Lexer\n") + add("\tredef fun start_state do return dfastate_{names[automaton.start]}\n") + add("end\n") + + add("redef class Object\n") + for s in automaton.states do + var n = names[s] + add("\tprivate fun dfastate_{n}: DFAState{n} do return once new DFAState{n}\n") + end + add("end\n") + + add("class MyNToken\n") + add("\tsuper NToken\n") + add("end\n") + + for s in automaton.states do + var n = names[s] + add("class DFAState{n}\n") + add("\tsuper DFAState\n") + if automaton.accept.has(s) then + var token + if automaton.tags.has_key(s) then + token = automaton.tags[s].first + else + token = null + end + add("\tredef fun is_accept do return true\n") + add("\tredef fun make_token(position, text) do\n") + if token != null and token.name == "Ignored" then + add("\t\treturn null\n") + else + if token == null then + add("\t\tvar t = new MyNToken\n") + else + add("\t\tvar t = new {token.cname}\n") + end + add("\t\tt.position = position\n") + add("\t\tt.text = text\n") + add("\t\treturn t\n") + end + add("\tend\n") + end + var trans = new ArrayMap[Int, State] + for t in s.outs do + var sym = t.symbol + assert sym != null + trans[sym] = t.to + end + if trans.is_empty then + # Do nothing, inherit the trans + else if trans.length == 1 then + var sym = trans.keys.first + var next = trans.values.first + add("\tredef fun trans(c) do\n") + add("\t\tif c.ascii == {sym} then return dfastate_{names[next]}\n") + add("\t\treturn null\n") + add("\tend\n") + else + add("\tredef fun trans(c) do\n") + for sym, next in trans do + add("\t\tif c.ascii == {sym} then return dfastate_{names[next]}\n") + end + add("\t\treturn null\n") + add("\tend\n") + end + add("end\n") + end + + self.out.close + end +end + +# A state in a finite automaton +class State + # Outgoing transitions + + var outs = new Array[Transition] + # Ingoing tyransitions + var ins = new Array[Transition] + + # Add a transitions to `to` on `symbol` (null means epsilon) + fun add_trans(to: State, symbol: nullable Int): Transition + do + var t = new Transition(self, to, symbol) + outs.add(t) + to.ins.add(t) + return t + end +end + +# A transition in a finite automaton +class Transition + # The source state + var from: State + # The destination state + var to: State + # The symbol on the transition (null means epsilon) + var symbol: nullable Int + + # Remove the transition from the automaton + # Detash from `from` and `to` + fun delete + do + from.outs.remove(self) + to.ins.remove(self) + end +end diff --git a/contrib/nitcc/examples/calc.nit b/contrib/nitcc/examples/calc.nit new file mode 100644 index 0000000..1ee7bc3 --- /dev/null +++ b/contrib/nitcc/examples/calc.nit @@ -0,0 +1,82 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Example of a calculation used nitcc +# see `calc.sablecc` for the grammar +module calc + +# Reuse the test program to simplify the code +import calc_test_parser + +# The main evaluator, as a visitiopn that stack values +class Calulator + super Visitor + + # The stack of values + var stack = new Array[Int] + + redef fun visit(n) do n.accept_calculator(self) +end + +redef class Node + # Default caculation is to visit the childrens + fun accept_calculator(v: Calulator) do visit_children(v) +end + +redef class Nint + redef fun accept_calculator(v) do v.stack.push(text.to_i) +end + +redef class Ne_add + redef fun accept_calculator(v) do + super + v.stack.push(v.stack.pop+v.stack.pop) + end +end + +redef class Ne_sub + redef fun accept_calculator(v) do + super + var n1 = v.stack.pop + v.stack.push(v.stack.pop-n1) + end +end + +redef class Ne_neg + redef fun accept_calculator(v) do + super + v.stack.push(-v.stack.pop) + end +end + +redef class Ne_mul + redef fun accept_calculator(v) do + super + v.stack.push(v.stack.pop*v.stack.pop) + end +end + +redef class Ne_div + redef fun accept_calculator(v) do + super + var n1 = v.stack.pop + v.stack.push(v.stack.pop/n1) + end +end + +var t = new MyTest +var n = t.main +var v = new Calulator +v.enter_visit(n) +print v.stack.pop diff --git a/contrib/nitcc/examples/calc.sablecc b/contrib/nitcc/examples/calc.sablecc new file mode 100644 index 0000000..077aad5 --- /dev/null +++ b/contrib/nitcc/examples/calc.sablecc @@ -0,0 +1,22 @@ +/* A simple calculator, see calc.nit */ +Grammar calc; + +Lexer +d = '0'..'9'; +int = d+; +blank = (' '|'\n')+; + +Parser +Ignored blank; +e = + {add:} e '+' f | + {sub:} e '-' f | + f {->f}; +f {->e} = + {mul:} f '*' a | + {div:} f '/' a | + a {->a}; +a {->e} = + {int:} int | + {par:} '(' e ')' | + {neg:} '-' a ; diff --git a/contrib/nitcc/examples/json.sablecc b/contrib/nitcc/examples/json.sablecc new file mode 100644 index 0000000..4ec4c55 --- /dev/null +++ b/contrib/nitcc/examples/json.sablecc @@ -0,0 +1,31 @@ +Grammar json; + +Lexer + +number = int frac? exp; +int = '-'? d+; +d = '0'..'9'; +frac = '.' d+; +exp = e d+; +e = ('e'|'E') ('+'|'-')?; + +string = '"' (ch-'\\'-'"' | '\\'ch)+ '"'; +ch = ' '..'~'; + +blank = (' '|'\n'|'\t')+; + +Parser +Ignored blank; + +value = + {object:} '{' members? '}' | + {array:} '[' elements? ']' | + number | + string | + 'true' | + 'false' | + 'null' ; + +members = members ',' pair | pair ; +pair = string ':' value ; +elements = elements ',' value | value ; diff --git a/contrib/nitcc/examples/minilang.minilang b/contrib/nitcc/examples/minilang.minilang new file mode 100644 index 0000000..7347ea9 --- /dev/null +++ b/contrib/nitcc/examples/minilang.minilang @@ -0,0 +1,28 @@ +a=1+2; +a=a*3; +print(a-4); +println(); + +f = 1; +fn = 0; +while (f < 500) { + t = f; + f = f + fn; + fn = t; +} +print("le plus petit nombre de Fibbonacci > 500 est "); +print(f); +println(); + +print("Plus ou moins ? (hint la reponse est 42)"); +println(); +goal = 42; +lu = -1; +while (lu != goal) { + print("Votre choix: "); + lu = read(); + if (lu > goal) { print("c'est plus petit."); println(); } + if (lu < goal) { print("c'est plus grand."); println(); } +} +print("C'est bon."); +println(); diff --git a/contrib/nitcc/examples/minilang.nit b/contrib/nitcc/examples/minilang.nit new file mode 100644 index 0000000..c639f14 --- /dev/null +++ b/contrib/nitcc/examples/minilang.nit @@ -0,0 +1,182 @@ +import minilang_test_parser + +class Interpretor + super Visitor + var stack = new Array[Int] + var bstack = new Array[Bool] + var vars = new HashMap[String, Int] + + redef fun visit(n) do n.accept_calculator(self) +end + +redef class Node + fun accept_calculator(v: Interpretor) do visit_children(v) +end + +redef class Nint + redef fun accept_calculator(v) do v.stack.push(text.to_i) +end + +redef class Ns_assign + redef fun accept_calculator(v) do + super + v.vars[n_id.text] = v.stack.pop + end +end + +redef class Ns_print + redef fun accept_calculator(v) do + super + printn v.stack.pop + end +end +redef class Ns_print_str + redef fun accept_calculator(v) do + var text = n_str.text + text = text.substring(1, text.length-2) + printn text + end +end +redef class Ns_println + redef fun accept_calculator(v) do + print "" + end +end +redef class Ns_if + redef fun accept_calculator(v) do + v.enter_visit(n_c) + if v.bstack.pop then + v.enter_visit(n_then) + else + var nelse = n_else + if nelse != null then v.enter_visit(nelse) + end + end +end +redef class Ns_while + redef fun accept_calculator(v) do + loop + v.enter_visit(n_c) + if not v.bstack.pop then break + v.enter_visit(n_stmts) + end + end +end + + +redef class Nc_and + redef fun accept_calculator(v) do + super + var b1 = v.bstack.pop + var b2 = v.bstack.pop + v.bstack.push(b1 and b2) + end +end + +redef class Nc_or + redef fun accept_calculator(v) do + super + var b1 = v.bstack.pop + var b2 = v.bstack.pop + v.bstack.push(b1 or b2) + end +end + +redef class Nc_not + redef fun accept_calculator(v) do + super + v.bstack.push(not v.bstack.pop) + end +end + +redef class Nc_eq + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop == v.stack.pop) + end +end + +redef class Nc_ne + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop != v.stack.pop) + end +end + +redef class Nc_lt + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop > v.stack.pop) + end +end + +redef class Nc_le + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop >= v.stack.pop) + end +end + +redef class Nc_gt + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop < v.stack.pop) + end +end + +redef class Nc_ge + redef fun accept_calculator(v) do + super + v.bstack.push(v.stack.pop <= v.stack.pop) + end +end + +redef class Ne_add + redef fun accept_calculator(v) do + super + v.stack.push(v.stack.pop+v.stack.pop) + end +end +redef class Ne_sub + redef fun accept_calculator(v) do + super + var n1 = v.stack.pop + v.stack.push(v.stack.pop-n1) + end +end +redef class Ne_neg + redef fun accept_calculator(v) do + super + v.stack.push(-v.stack.pop) + end +end +redef class Ne_mul + redef fun accept_calculator(v) do + super + v.stack.push(v.stack.pop*v.stack.pop) + end +end +redef class Ne_div + redef fun accept_calculator(v) do + super + var n1 = v.stack.pop + v.stack.push(v.stack.pop/n1) + end +end +redef class Ne_var + redef fun accept_calculator(v) do + v.stack.push v.vars[n_id.text] + end +end +redef class Ne_read + redef fun accept_calculator(v) do + var t = gets + v.stack.push(t.to_i) + end +end + +var t = new MyTest +var n = t.main + +var v = new Interpretor +v.enter_visit(n) diff --git a/contrib/nitcc/examples/minilang.sablecc b/contrib/nitcc/examples/minilang.sablecc new file mode 100644 index 0000000..7c951c0 --- /dev/null +++ b/contrib/nitcc/examples/minilang.sablecc @@ -0,0 +1,57 @@ +/* Grammar of a mini procedural programming language */ +Grammar minilang; + +Lexer +l = 'a'..'z'|'A'..'Z'|'_'; +d = '0'..'9'; +id = l (l|d)*; +int = d+; +str = '"' (' '..'~' - '"')* '"'; +blank = ' ' | '\n' | '\t'; + +Parser +Ignored blank; + +prog = s*; + +s = + {assign:} id '=' e ';' | + {print:} 'print' '(' e ')' ';' | + {print_str:} 'print' '(' str ')' ';' | + {println:} 'println' '(' ')' ';' | + {while:} 'while' '(' c ')' stmts | + {if:} 'if' '(' c ')' [then:]stmts else? ; + +stmts = '{' s* '}' ; + +else = 'else' stmts; + +e = + {add:} [left:]e '+' [right:]e2 | + {sub:} [left:]e '-' [right:]e2 | + e2 {->e2}; +e2 {->e} = + {mul:} [left:]e2 '*' [right:]e3 | + {div:} [left:]e2 '/' [right:]e3 | + e3 {->e3}; +e3 {->e} = + {neg:} '-' e3 | + {lit:} int | + {par:} '(' e ')' | + {var:} id | + {read:} 'read' '(' ')' ; + +c = + {or:} [left:]c '||' [right:]c2 | + c2 {->c2}; +c2 {->c} = + {and:} [left:]c2 '&&' [right:]c3 | + c3 {->c3}; +c3 {->c} = + {not:} 'not' [c:]c3 | + {eq:} [left:]e '=' [right:]e | + {ne:} [left:]e '!=' [right:]e | + {lt:} [left:]e '<' [right:]e | + {le:} [left:]e '<=' [right:]e | + {gt:} [left:]e '>' [right:]e | + {ge:} [left:]e '>=' [right:]e ; diff --git a/contrib/nitcc/examples/mkml.sh b/contrib/nitcc/examples/mkml.sh new file mode 100755 index 0000000..1b49c51 --- /dev/null +++ b/contrib/nitcc/examples/mkml.sh @@ -0,0 +1,5 @@ +set -e +set -x +../nitcc minilang.sablecc +../../../bin/nitc minilang.nit -v -I .. +./minilang minilang.minilang diff --git a/contrib/nitcc/grammar.nit b/contrib/nitcc/grammar.nit new file mode 100644 index 0000000..6cb7956 --- /dev/null +++ b/contrib/nitcc/grammar.nit @@ -0,0 +1,1054 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# A gramar describing a language +class Gram + # The productions (non-terminal) of the conctete grammar + var prods = new Array[Production] + + # The additionnal abstract productions of the grammar + # TODO clean AST + var ast_prods = new Array[Production] + + # The tokens (terminals) of the grammar + var tokens = new Array[Token] + + # Dump of the concrete grammar and the transformations + fun pretty: String + do + var res = new Buffer + for p in prods do + if p.spe != null then + res.append("{p.name} \{-> {p.spe.name}\}=\n") + else + res.append("{p.name} =\n") + end + var last = p.alts.last + for a in p.alts do + res.append("\t\{{a.name}:\} {a.elems.join(" ")}") + if a.codes == null then a.make_codes + res.append("\n\t\t\{-> {a.codes.join(", ")}\}") + if a == last then res.append(" ;\n") else res.append(" |\n") + end + if p.is_nullable then res.append "\t// is nullable\n" + if not p.firsts.is_empty then res.append "\t// firsts: {p.firsts.join(" ")}\n" + if not p.afters.is_empty then res.append "\t// afters: {p.afters.join(" ")}\n" + end + return res.to_s + end + + # Inline (ie. remove from the conctete grammar) some production + # REQUIRE: no circular production in `prods` + fun inline(prods: Collection[Production]) + do + for p in self.prods do + for a in p.alts.to_a do + var to_inline = false + for e in a.elems do + if e isa Production and prods.has(e) then to_inline = true + end + if not to_inline then continue + + if a.codes == null then a.make_codes + + var a0 = new Alternative(p, a.name, new Array[Element]) + a0.trans = true + a0.codes = new Array[Code] + var pool = [a0] + var pool2 = new Array[Alternative] + for e in a.elems do + if not e isa Production or not prods.has(e) then + for x in pool do + x.elems.add(e) + x.codes.add(new CodePop) + end + continue + end + if p == e then + print "Circular inlining on {p} :: {a}" + abort + end + pool2.clear + for a2 in e.alts do + if a2.codes == null then a2.make_codes + for x in pool do + var name = a.name + "_" + pool2.length.to_s + var na = new Alternative(p, name, new Array[Element]) + na.trans = true + pool2.add(na) + na.elems.add_all(x.elems) + na.elems.add_all(a2.elems) + na.codes = new Array[Code] + na.codes.add_all(x.codes.as(not null)) + na.codes.add_all(a2.codes.as(not null)) + end + end + var tmp = pool + pool = pool2 + pool2 = tmp + end + for x in pool do + x.codes.add(a.codes.last) + end + p.ast_alts.add(a) + p.alts.remove(a) + p.alts.add_all(pool) + end + end + for p in prods do + self.prods.remove(p) + self.ast_prods.add(p) + end + end + + # Compute a LR automaton + fun lr0: LRAutomaton + do + analyse + + var start = new Production("_start") + start.accept = true + var eof = new Token("Eof") + tokens.add(eof) + start.new_alt("Start", self.prods.first, eof) + prods.add(start) + var first = new LRState("Start") + first.number = 0 + for i in start.start_state do first.add(i) + + var automaton = new LRAutomaton(self) + + var todo = new List[LRState] + todo.add first + var seen = new HashSet[LRState] + seen.add first + + while not todo.is_empty do + var state = todo.shift + + #print state + automaton.states.add(state) + state.analysis + + var nexts = new HashMap[Element, LRState] + for i in state.items do + var e = i.next + if e == null then continue + if nexts.has_key(e) then + nexts[e].add(i.avance) + else + var name + if state == automaton.states.first then + name = e.to_s + else + name = "{state.name} {e}" + end + var next = new LRState(name) + nexts[e] = next + next.add(i.avance) + end + end + + for e, next in nexts do + + #print "#states: {seen.length}" + + var new_state = true + for n in seen do + if n == next then + for i in next.items do + if n.add(i) then n.extends(i) + end + next = n + new_state = false + break + end + end + + if new_state then + next.number = seen.length + assert not seen.has(next) + seen.add(next) + todo.add(next) + end + + var t = new LRTransition(state, next, e) + state.outs.add t + next.ins.add t + end + end + return automaton + end + + # Compute `nullables`, `firsts` and `afters` of productions + fun analyse + do + loop + var changed = false + for p in prods do + if p.is_nullable then continue + for a in p.alts do + var nullabl = true + for e in a.elems do + if e isa Token then + nullabl = false + break + else if e isa Production then + if not e.is_nullable then nullabl = false + break + else + abort + end + end + if nullabl then + p.is_nullable = true + changed = true + end + end + end + if not changed then break + end + + loop + var changed = false + for p in prods do + var fs = p.firsts + for a in p.alts do + for e in a.elems do + if e isa Token then + if try_add(fs, e) then changed = true + break + else if e isa Production then + for t in e.firsts do + if try_add(fs, t) then changed = true + end + if not e.is_nullable then break + else + abort + end + end + end + end + if not changed then break + end + + loop + var changed = false + for p1 in prods do + for a in p1.alts do + var p0: nullable Production = null + for e in a.elems do + var p = p0 + if e isa Production then p0 = e else p0 = null + if p == null then continue + + var afs = p.afters + + if e isa Token then + if try_add(afs, e) then changed = true + else if e isa Production then + for t in e.firsts do + if try_add(afs, t) then changed = true + end + if e.is_nullable then + for t in e.afters do + if try_add(afs, t) then changed = true + end + end + else + abort + end + end + if p0 != null then + var afs = p0.afters + for t in p1.afters do + if try_add(afs, t) then changed = true + end + end + end + end + if not changed then break + end + end + + # used by `analyse` + private fun try_add(set: Set[Token], t: Token): Bool + do + var res = not set.has(t) + if res then set.add(t) + return res + end + +end + +# A production of a grammar +class Production + super Element + # The alternative of the production + var alts = new Array[Alternative] + + # Additionnal alternatives in the AST + var ast_alts = new Array[Alternative] + + # Is self the accept production + var accept = false + + # Is self transformed to a other production for the AST + # FIXME: cleaup AST + var spe: nullable Production writable = null + + # Is self contains only a single alternative (then no need for a abstract production class in the AST) + # FIXME cleanup AST + var altone writable = false + + # The cname of the class in the AST + # FIXME: cleanup AST + redef fun acname do + if spe != null then return spe.acname + return super + end + + # Is the production nullable + var is_nullable = false + # The first tokens of the production + var firsts = new HashSet[Token] + # The tokens that may follows the production (as in SLR) + var afters = new HashSet[Token] + + + # Crate a new empty alternative + fun new_alt0(name: String): Alternative + do + var a = new Alternative(self, name, new Array[Element]) + alts.add a + return a + end + + # Crate a new alternative with some elements + fun new_alt(name: String, elems: Element...): Alternative + do + var a = new Alternative(self, name, elems) + alts.add a + return a + end + + # Crate a new alternative with some elements + fun new_alt2(name: String, elems: Array[Element]): Alternative + do + var a = new Alternative(self, name, elems) + alts.add a + return a + end + + # Return a set of items for the production + fun start_state: Array[Item] + do + var res = new Array[Item] + for a in alts do + res.add new Item(a, 0) + end + return res + end + + # States in the LR automaton that has a outgoing transition on self + var gotos = new ArraySet[LRState] +end + +# An alternative of a production +class Alternative + # The production + var prod: Production + + # The name of the alternative + var name: String writable + + # The elements of the alternative + var elems: Array[Element] + + # The name of the elements + var elems_names = new Array[nullable String] + + # Return a name for a given element (or a number if unamed) + fun elemname(i: Int): String + do + if i >= elems_names.length then return "{i}" + var n = elems_names[i] + if n == null then return "{i}" + return n + end + + redef fun to_s do return "{prod.name}::{name}={elems.join(" ")}" + + # A mangled name + fun cname: String do + return "N{name.to_cmangle}" + end + + # The code for the reduction + var codes: nullable Array[Code] writable = null + + # Is the alternative transformed (ie not in the AST) + var trans writable = false + + # Imitialize codes with the elements + fun make_codes + do + if codes != null then return + var codes = new Array[Code] + self.codes = codes + for e in elems do + codes.add(new CodePop) + end + codes.add(new CodeNew(self)) + end +end + +# A step in the construction of the AST. used to modelize transformations +interface Code +end +# Get a element from the stack +class CodePop + super Code + redef fun to_s do return "pop" +end +# Allocate a new AST node for an alternative using the correct number of poped elements +class CodeNew + super Code + var alt: Alternative + redef fun to_s do return "New {alt.name}/{alt.elems.length}" +end +# Get null +class CodeNull + super Code + redef fun to_s do return "null" +end + +# Elements of an alternative. +# Either a `Production` or a `Token` +abstract class Element + # The name of the element + var name: String + redef fun to_s do return name + + private var acname_cache: nullable String = null + + # The mangled name of the element + fun cname: String do return "N{name.to_cmangle}" + + # the name of the class in the AST + fun acname: String do + var res = acname_cache + if res == null then + res = "N{to_s.to_cmangle}" + acname_cache = res + end + return res + end + fun acname=(s: String) do acname_cache = s +end + +# A terminal element +class Token + super Element + # States of the LR automatio that shift on self + var shifts = new ArraySet[LRState] + # States of the LR automatio that reduce on self in the lookahead(1) + var reduces = new ArraySet[LRState] +end + +# + +# A LR automaton +class LRAutomaton + # The grammar of the automaton + var grammar: Gram + + # The set of states + var states = new Array[LRState] + + # Dump of the automaton + fun pretty: String + do + var res = new Array[String] + res.add "* LRAutomaton: {states.length} states\n" + for s in states do + res.add "s{s.number} {s.name}\n" + res.add "\tCORE\n" + for i in s.core do + res.add "\t\t{i}\n" + end + res.add "\tOTHER ITEMS\n" + for i in s.items do + if s.core.has(i) then continue + res.add "\t\t{i}\n" + end + res.add "\tTRANSITIONS {s.outs.length}\n" + for t in s.outs do + res.add "\t\t{t.elem} |-> s{t.to.number}\n" + end + res.add "\tACTIONS\n" + if s.is_lr0 then + res.add "\t\tSTATE LR0\n" + else + res.add "\t\tSTATE LALR\n" + for t, a in s.guarded_reduce do + if a.length > 1 then + res.add "\t\t/!\\ REDUCE/REDUCE CONFLICT\n" + break + else if s.shifts.has(t) then + res.add "\t\t/!\\ SHIFT/REDUCE CONFLICT\n" + break + end + end + end + if not s.shifts.is_empty then + res.add "\t\tSHIFT {s.shifts.join(" ")}\n" + end + for r in s.reduces do + res.add "\t\tREDUCE {r}\n" + end + end + return res.to_s + end + + # Generate a graphviz file of the automaton + fun to_dot(path: String) + do + var f = new OFStream.open(path) + f.write("digraph g \{\n") + f.write("rankdir=LR;\n") + f.write("node[shape=Mrecord,height=0];\n") + + for s in states do + f.write "s{s.number} [label=\"{s.number} {s.name.escape_to_dot}|" + for i in s.core do + f.write "{i.to_s.escape_to_dot}\\l" + end + f.write("|") + for i in s.items do + if s.core.has(i) then continue + f.write "{i.to_s.escape_to_dot}\\l" + end + f.write "\"" + if not s.is_lr0 then + var conflict = false + for t, a in s.guarded_reduce do + if a.length > 1 then + f.write ",color=red" + conflict = true + break + else if s.shifts.has(t) then + f.write ",color=orange" + conflict = true + break + end + end + if not conflict then + f.write ",color=blue" + end + end + f.write "];\n" + for t in s.outs do + f.write "s{s.number} -> s{t.to.number} [label=\"{t.elem.to_s.escape_to_dot}\"];\n" + end + end + f.write("\}\n") + f.close + end + + # Generate the parser of the automaton + fun gen_to_nit(filepath: String) + do + var gen = new Generator + gen.gen_to_nit(self) + var f = new OFStream.open(filepath) + for s in gen.out do + f.write(s) + f.write("\n") + end + f.close + end +end + +redef class String + # escape string used in labels for graphviz + fun escape_to_dot: String + do + return escape_more_to_c("|\{\}") + end +end + +private class Generator + var out = new Array[String] + fun add(s: String) do out.add(s) + fun gen_to_nit(autom: LRAutomaton) + do + var states = autom.states + var gram = autom.grammar + + add "# Parser generated by nitcc" + add "import nitcc_runtime" + + add "class MyParser" + add "\tsuper Parser" + add "\tredef fun start_state do return state_{states.first.cname}" + add "end" + + add "redef class Object" + for s in states do + add "\tprivate fun state_{s.cname}: LRState{s.cname} do return once new LRState{s.cname}" + end + for p in gram.prods do + add "\tprivate fun goto_{p.cname}: Goto_{p.cname} do return once new Goto_{p.cname}" + end + add "end" + + add "redef class NToken" + for s in states do + if not s.need_guard then continue + add "\t# guarded action for state {s.name}" + add "\t# {s.shifts.length} shift(s) and {s.reduces.length} reduce(s)" + add "\tprivate fun action_s{s.cname}(parser: Parser) do" + if s.reduces.length != 1 then + add "\t\tparser.parse_error" + else + gen_reduce_to_nit(s.reduces.first) + end + add "\tend" + end + add "end" + + for t in gram.tokens do + if t.name == "Eof" then + add "redef class {t.cname}" + else + add "class {t.cname}" + end + add "\tsuper NToken" + for s in t.shifts do + if not s.need_guard then continue + add "\tredef fun action_s{s.cname}(parser) do" + gen_shift_to_nit(s, t) + add "\tend" + end + for s in t.reduces do + if not s.need_guard then continue + if s.reduces.length <= 1 then continue + add "\tredef fun action_s{s.cname}(parser) do" + gen_reduce_to_nit(s.guarded_reduce[t].first.alt) + add "\tend" + end + add "\tredef fun node_name do return \"{t.name.escape_to_nit}\"" + add "end" + end + + add "redef class LRGoto" + for s in states do + if s.gotos.length <= 1 then continue + add "\tprivate fun goto_s{s.cname}(parser: Parser) do abort" + end + add "end" + + for p in gram.prods do + add "class Goto_{p.cname}" + add "\tsuper LRGoto" + for s in p.gotos do + if s.gotos.length <= 1 then continue + add "\tredef fun goto_s{s.cname}(parser) do" + gen_goto_to_nit(s, p) + add "\tend" + end + add "end" + end + + var ps = gram.prods.to_a + ps.add_all(gram.ast_prods) + for p in ps do + if p.spe == null and not p.altone then + if p.name.has_suffix("?") or p.name.has_suffix("+") then continue + add "class {p.acname}" + add "\tsuper NProd" + add "\tredef fun node_name do return \"{p.name.escape_to_nit}\"" + add "end" + end + + var als = p.alts.to_a + als.add_all(p.ast_alts) + for a in als do + if a.trans then continue + add "class {a.cname}" + if p.altone then + add "\tsuper NProd" + else + add "\tsuper {p.acname}" + end + add "\tredef fun node_name do return \"{a.name.escape_to_nit}\"" + var initarg = new Array[String] + for i in [0..a.elems.length[ do + add "\tvar n_{a.elemname(i)}: {a.elems[i].acname}" + initarg.add("n_{a.elemname(i)}: {a.elems[i].acname}") + end + if initarg.is_empty then + add "\tinit do end" + else + add "\tinit({initarg.join(", ")}) do" + for i in [0..a.elems.length[ do + add "\t\tself.n_{a.elemname(i)} = n_{a.elemname(i)}" + end + add "\tend" + end + add "\tredef fun number_of_children do return {a.elems.length}" + add "\tredef fun child(i) do" + for i in [0..a.elems.length[ do + add "\t\tif i == {i} then return n_{a.elemname(i)}" + end + add "\t\tabort" + add "\tend" + add "end" + end + end + + for s in states do + add "# State {s.name}" + add "private class LRState{s.cname}" + add "\tsuper LRState" + + add "\tredef fun to_s do return \"{s.name.escape_to_nit}\"" + + var err = new Array[String] + for t in s.outs do + var e = t.elem + if e isa Production then err.add e.name + end + if err.is_empty then for t in s.outs do + var e = t.elem + if e isa Token then err.add e.name + end + + add "\tredef fun error_msg do return \"{err.join(", ").escape_to_nit}\"" + + add "\tredef fun action(parser) do" + if s.need_guard then + add "\t\tparser.peek_token.action_s{s.cname}(parser)" + else if s.reduces.length == 1 then + gen_reduce_to_nit(s.reduces.first) + else + abort + end + add "\tend" + + if not s.gotos.is_empty then + add "\tredef fun goto(parser, goto) do" + if s.gotos.length > 1 then + add "\t\tgoto.goto_s{s.cname}(parser)" + else + gen_goto_to_nit(s, s.gotos.first) + end + add "\tend" + end + + add "end" + end + + + end + + fun gen_shift_to_nit(s: LRState, t: Token) + do + var dest = s.trans(t) + add "\t\tparser.shift(state_{dest.cname})" + + end + + fun gen_goto_to_nit(s: LRState, p: Production) + do + var dest = s.trans(p) + add "\t\tparser.push(state_{dest.cname})" + end + + fun gen_reduce_to_nit(alt: Alternative) + do + add "\t\t# REDUCE {alt}" + var i = alt.elems.length - 1 + for e in alt.elems.to_a.reversed do + add "\t\tvar n{i} = parser.pop.as({e.acname})" + i -= 1 + end + + if alt.name.has_suffix("+_more") then + add "\t\tvar prod = n0" + add "\t\tn0.items.add(n1)" + else if alt.name.has_suffix("+_one") then + add "\t\tvar prod = new {alt.prod.acname}" + add "\t\tprod.items.add(n0)" + else + alt.make_codes + var cpt = 0 + i = 0 + var st = new Array[String] + for c in alt.codes.as(not null) do + if c isa CodePop then + st.add "n{i}" + i += 1 + else if c isa CodeNull then + st.add "null" + else if c isa CodeNew then + var calt = c.alt + cpt += 1 + var from = st.length - calt.elems.length + var args = new List[String] + for j in [from..st.length[ do + args.unshift(st.pop) + end + + if args.is_empty then + add "\t\tvar p{cpt} = new {calt.cname}" + else + add "\t\tvar p{cpt} = new {calt.cname}({args.join(", ")})" + end + #var x = 0 + #for j in [from..st.length[ do + #if st[j] == "null" then continue + #add "\t\tp{cpt}.n_{calt.elemname(x)} = {st[j]}" + #x += 1 + #end + st.add("p{cpt}") + end + end + assert st.length == 1 + add "\t\tvar prod = {st.first}" + end + + add "\t\tparser.node_stack.push prod" + if alt.prod.accept then + add "\t\tparser.stop = true" + else + add "\t\tparser.goto(goto_{alt.prod.cname})" + end + end +end + +# A state in a LR automaton +class LRState + # name of the automaton (short part from the start) + var name: String + + # malglen name + fun cname: String do return name.to_cmangle + + # number + var number: Int = -1 + + # Set of all items + var items = new HashSet[Item] + + # Set of items only in the core + var core = new HashSet[Item] + + # Outgoing transitions + var ins = new Array[LRTransition] + + # Ingoing transitions + var outs = new Array[LRTransition] + + # trans function + fun trans(e: Element): nullable LRState + do + for t in outs do if t.elem == e then return t.to + return null + end + + redef fun ==(o) do return o isa LRState and core == o.core + redef fun hash do return items.length + + redef fun to_s do return items.join(" ; ") + + # Add and item in the core + fun add(i: Item): Bool + do + #if items.has(i) then return + + #print "add {i} in {inspect}={self}" + var found = false + for i2 in items do + if i.alt == i2.alt and i.pos == i2.pos then + if i2.future.has_all(i.future) then return false + i2.future.add_all(i.future) + found = true + + break + end + end + if not found then + items.add(i) + if i.pos > 0 or i.alt.prod.accept then core.add(i) + end + return true + end + + # Recusively extends item outside the core + fun extends(i: Item) + do + var e = i.next + if e == null then return + if not e isa Production then return + var la = i.lookahead + for i2 in e.start_state do + i2.future.add_all(la) + if add(i2) then extends(i2) + end + end + + # Set of all reductions + var reduces = new ArraySet[Alternative] + # Set of all shifts + var shifts = new ArraySet[Token] + # Set of all goto + var gotos = new ArraySet[Production] + # Reduction guarded by tokens + var guarded_reduce = new HashMap[Token, Array[Item]] + # Shitfs guarded by tokens + var guarded_shift = new HashMap[Token, Array[Item]] + + # Does the state need a guard to perform an action? + fun need_guard: Bool do return not shifts.is_empty or reduces.length > 1 + + # Is the state LR0 + fun is_lr0: Bool do return reduces.length <= 1 and shifts.is_empty or reduces.is_empty + + # compute guards and conflicts + fun analysis + do + for i in items.to_a do + extends(i) + end + + for i in items do + var n = i.next + if n == null then + reduces.add(i.alt) + #for t in i.alt.prod.afters do + for t in i.future do + t.reduces.add(self) + if guarded_reduce.has_key(t) then + guarded_reduce[t].add(i) + else + guarded_reduce[t] = [i] + end + end + else if n isa Token then + shifts.add(n) + n.shifts.add(self) + if guarded_shift.has_key(n) then + guarded_shift[n].add(i) + else + guarded_shift[n] = [i] + end + else if n isa Production then + gotos.add(n) + n.gotos.add(self) + else + abort + end + end + for t, a in guarded_reduce do + if a.length > 1 then + print "REDUCE/REDUCE Conflict on state {self.number} {self.name} for token {t}:" + for i in a do print "\t{i}" + else if guarded_shift.has_key(t) then + print "SHIFT/REDUCE Conflict on state {self.number} {self.name} for token {t}:" + for i in a do print "\t{i}" + for i in guarded_shift[t] do print "\t{i}" + end + end + end +end + +# A transition in a LR automaton +class LRTransition + # The origin state + var from: LRState + # The testination state + var to: LRState + # The element labeling the transition + var elem: Element +end + +# A alternative with a cursor (dot) and possibly a future +class Item + # The alternative + var alt: Alternative + # The dot index (0 means before the first element) + var pos: Int + # The possible future + var future = new ArraySet[Token] + + redef fun ==(o) do return o isa Item and alt == o.alt and pos == o.pos + redef fun hash do return alt.hash + pos + + redef fun to_s + do + var b = new Buffer + b.append("{alt.prod.name}::{alt.name}=") + for i in [0..alt.elems.length[ + do + if pos == i then b.append(".") else b.append(" ") + b.append(alt.elems[i].to_s) + end + if pos == alt.elems.length then b.append(".") + if not future.is_empty then + b.append("/\{") + b.append(future.join(" ")) + b.append("\}") + end + return b.to_s + end + + # The element thatr follow the dot, null if the fdot is at the end + fun next: nullable Element + do + if pos >= alt.elems.length then return null + return alt.elems[pos] + end + + # SLR loohahead + fun lookahead: Set[Token] + do + var res = new HashSet[Token] + var p = pos + 1 + while p < alt.elems.length do + var e = alt.elems[p] + if e isa Token then + res.add(e) + break + else if e isa Production then + res.add_all(e.firsts) + if not e.is_nullable then break + end + p += 1 + end + if p >= alt.elems.length then + res.add_all(future) + end + return res + end + + # The item that advanced once + fun avance: Item + do + var res = new Item(alt, pos+1) + res.future.add_all(future) + return res + end +end diff --git a/contrib/nitcc/mk b/contrib/nitcc/mk new file mode 100755 index 0000000..5c7a0cf --- /dev/null +++ b/contrib/nitcc/mk @@ -0,0 +1,33 @@ +set -e +set -x + +NITC=../../bin/nitg + +echo "**************************" + +$NITC nitcc_parser_gen.nit -v +./nitcc_parser_gen + +echo "**************************" + +$NITC nitcc.nit -v +cp nitcc nitcc0 + +echo "**************************" + +./nitcc nitcc.sablecc +$NITC nitcc.nit +cp nitcc nitcc1 + +echo "**************************" + +./nitcc nitcc.sablecc +$NITC nitcc.nit + +echo "**************************" + +cd examples +../nitcc calc.sablecc +../$NITC calc.nit -v -I .. +./calc -e "1+2*3-40/5+9------1" + diff --git a/contrib/nitcc/nitcc.nit b/contrib/nitcc/nitcc.nit new file mode 100644 index 0000000..3d172ef --- /dev/null +++ b/contrib/nitcc/nitcc.nit @@ -0,0 +1,147 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# nitcc, a parser and lexer generator for Nit +module nitcc + +import nitcc_semantic + +# Load the grammar file + +if args.is_empty then + print "usage: nitcc | -" + exit 1 +end +var fi = args.first + +var text +if fi != "-" then + var f = new IFStream.open(fi) + text = f.read_all + f.close +else + text = stdin.read_all +end + +# Parse the grammar file + +var l = new MyLexer(text) +var ts = l.lex + +var p = new MyParser +p.tokens.add_all ts + +var node = p.parse + +if not node isa NProd then + print node + exit 1 + abort +end + +var name = node.children.first.as(Ngrammar).children[1].as(Nid).text + +print "Grammar {name} (see {name}.gram.dot))" +node.to_dot("{name}.gram.dot") + +# Semantic analysis + +var v2 = new CollectNameVisitor +v2.start(node) +var gram = v2.gram + +if gram.prods.is_empty then + print "Error: grammar with no production" + exit(1) +end + +# Generate the LR automaton + +var lr = gram.lr0 + +var conflitcs = new ArraySet[Production] +for s in lr.states do for t, a in s.guarded_reduce do if a.length > 1 or s.guarded_shift.has_key(t) then + for i in a do conflitcs.add(i.alt.prod) +end + +if not conflitcs.is_empty then + print "Error: there is conflicts" +end + +if false then loop +if conflitcs.is_empty then break +print "Inline {conflitcs.join(" ")}" +gram.inline(conflitcs) +lr=gram.lr0 +end + +# Output concrete grammar and LR automaton + +var nbalts = 0 +for prod in gram.prods do nbalts += prod.alts.length +print "Concrete grammar: {gram.prods.length} productions, {nbalts} alternatives (see {name}.concrete_grammar.txt)" + +var pretty = gram.pretty +var f = new OFStream.open("{name}.concrete_grammar.txt") +f.write "// Concrete grammar of {name}\n" +f.write pretty +f.close + +print "LR automaton: {lr.states.length} states (see {name}.lr.dot and {name}.lr.txt)" +lr.to_dot("{name}.lr.dot") +pretty = lr.pretty +f = new OFStream.open("{name}.lr.txt") +f.write "// LR automaton of {name}\n" +f.write pretty +f.close + +# NFA and DFA + +var nfa = v2.nfa +print "NFA automaton: {nfa.states.length} states (see {name}.nfa.dot)" +nfa.to_dot("{name}.nfa.dot") + +var dfa = nfa.to_dfa +if dfa.tags.has_key(dfa.start) then + print "ERROR: Empty tokens {dfa.tags[dfa.start].join(" ")}" +end +dfa.solve_token_inclusion +for s, tks in dfa.tags do + if tks.length <= 1 then continue + print "ERROR: Conflicting tokens: {tks.join(" ")}" +end +print "DFA automaton: {dfa.states.length} states (see {name}.dfa.dot)" +dfa.to_dot("{name}.dfa.dot") + +# Generate Nit code + +print "Generate {name}_lexer.nit {name}_parser.nit {name}_test_parser.nit" +dfa.gen_to_nit("{name}_lexer.nit", "{name}_parser") +lr.gen_to_nit("{name}_parser.nit") + +f = new OFStream.open("{name}_test_parser.nit") +f.write """# Generated by nitcc for the language {{{name}}} +import nitcc_runtime +import {{{name}}}_lexer +import {{{name}}}_parser +class MyTest + super TestParser + redef fun name do return \"{{{name}}}\" + redef fun new_lexer(text) do return new MyLexer(text) + redef fun new_parser do return new MyParser +end +var t = new MyTest +t.main +""" +f.close diff --git a/contrib/nitcc/nitcc.sablecc b/contrib/nitcc/nitcc.sablecc new file mode 100644 index 0000000..9dc5579 --- /dev/null +++ b/contrib/nitcc/nitcc.sablecc @@ -0,0 +1,95 @@ +// The grammar of nitcc (subset of sablecc4) +Grammar nitcc; + +Lexer + +// Identifier, used for production, expressions, alternatives, etc. +id = ('a'..'z')('a'..'z'|'0'..'9'|'_')*; + +// A printable character (inside strings) +ch = ' ' .. '~'; + +// Literal strings +str = '\'' (ch-'\\'-'\''|'\\'ch)* '\''; + +// A char by decimal ascii +ch_dec = '#' ('0'..'9')+ ; + +// A single-line comment +comment = '//' ch* '\n'?; + +any = '\t'..'~'; +not_star = any - '*'; +not_star_not_slash = not_star - '/'; + +ccomment = '/*' not_star* ('*' (not_star_not_slash not_star*)?)* '*/'; + +unknown_keyword = 'A..Z'('A'..'Z'|'a'..'z'|'0'..'9'|'_')*; + +// Igndored stufs +blank = '\n' | '\t' | ' ' | comment | ccomment; + +Parser + +Ignored blank; + +grammar = 'Grammar' id ';' lexer_part? parser_part? reject?; + +reject = 'XXX' unknown_keyword ';'; + +lexer_part = 'Lexer' expr*; + +expr = id '=' re ';'; + +// No priority (yet) so just decompose +re = + {alter:} re '|' re1 | + re1 ; + +re1 {-> re} = + {minus:} re1 '-' re2 | + re2 ; + +re2 {-> re} = + {conc:} re2 re3 | + re3 ; + +re3 {-> re} = + {ques:} re3 '?' | + {star:} re3 '*' | + {plus:} re3 '+' | + {id:} id | + {str:} str | + {par:} '(' re ')' | + {class:} str '.' '.' str | + {any:} 'Any' | + {ch_dec:} ch_dec ; + + +parser_part = 'Parser' ign? prod*; + +ign = 'Ignored' id ';' ; + +prod = id ptrans? '=' alts ';'; + +ptrans = '{' '->' id '}'; +atrans = '{' '->' id '}'; + +alts = + {more:} alts '|' alt | + {one:} alt ; + +alt = altid? nelem* atrans?; + +altid = '{' id ':' '}' | '{' id '}'; + +nelem = elem | elemid elem; + +elemid = '[' id ':' ']' | '[' id ']' ':'; + +elem = + {id:} id | + {str:} str | + {star:} elem '*' | + {ques:} elem '?' | + {plus:} elem '+' ; diff --git a/contrib/nitcc/nitcc_lexer0.nit b/contrib/nitcc/nitcc_lexer0.nit new file mode 100644 index 0000000..50d590e --- /dev/null +++ b/contrib/nitcc/nitcc_lexer0.nit @@ -0,0 +1,163 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Ad-hoc hand-writen lexer for nitcc +# This avoid to commit (and relyon ) a generated lexer +# +module nitcc_lexer0 + +# Required for the tokens definitions +import nitcc_parser + +# Hand-writen lexer of nitcc +# Used only for the boostrap of the tool. +class MyLexer + var text: String + + var iter: Iterator[Char] = "".iterator + var pos = 0 + + var tokens = new Array[NToken] + + fun lex: Array[NToken] + do + iter = text.iterator + while iter.is_ok do + trim + if not iter.is_ok then break + var c = iter.item + iter.next + pos += 1 + if c == '*' then + tokens.add new Nstar + else if c == '?' then + tokens.add new Nques + else if c == '+' then + tokens.add new Nplus + else if c == '-' then + if iter.item == '>' then + iter.next + tokens.add new Narrow + else + tokens.add new Nminus + end + else if c == '(' then + tokens.add new Nopar + else if c == ')' then + tokens.add new Ncpar + else if c == '{' then + tokens.add new Nocur + else if c == '}' then + tokens.add new Nccur + else if c == '|' then + tokens.add new Npipe + else if c == ':' then + tokens.add new Ncolo + else if c == ';' then + tokens.add new Nsemi + else if c == '.' then + tokens.add new Ndot + else if c == '=' then + tokens.add new Neq + else if c == '\'' then + str + else if c >= 'a' and c <= 'z' then + id(c) + else if c >= 'A' and c <= 'Z' then + kw(c) + else if c == '/' and iter.is_ok and iter.item == '/' then + while iter.is_ok and iter.item != '\n' do iter.next + else + error(c) + end + end + tokens.add new NEof + return tokens + end + + fun error(c: Char) + do + print "pos {pos}: Lexer error on '{c}'." + abort + end + + fun str + do + var b = new Buffer + b.add('\'') + while iter.is_ok do + var c = iter.item + iter.next + if c == '\\' then + if not iter.is_ok then + error(c) + end + b.add(c) + c = iter.item + iter.next + else if c == '\'' then + b.add(c) + var token = new Nstr + token.text = b.to_s + tokens.add token + return + end + b.add c + end + error('\n') + abort + end + + fun id(c: Char) + do + var b = new Buffer + b.add c + while iter.is_ok do + c = iter.item + if c != '_' and (c<'a' or c >'z') and (c<'0' or c>'9') then + break + end + b.add c + iter.next + end + var token = new Nid + token.text = b.to_s + tokens.add token + end + + fun kw(c: Char) + do + var b = new Buffer + b.add c + while iter.is_ok do + c = iter.item + if c != '_' and (c<'a' or c >'z') and (c<'0' or c>'9') then + break + end + b.add c + iter.next + end + var token = new Nkw + token.text = b.to_s + tokens.add token + end + + fun trim + do + while iter.is_ok and iter.item <= ' ' do + iter.next + pos += 1 + end + end +end diff --git a/contrib/nitcc/nitcc_parser_gen.nit b/contrib/nitcc/nitcc_parser_gen.nit new file mode 100644 index 0000000..0118a4c --- /dev/null +++ b/contrib/nitcc/nitcc_parser_gen.nit @@ -0,0 +1,150 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Bootstraping the nitcc parser +# +# Instead of commiting a generated parser on each version, +# this program just generate the nitcc_parser using the API of `grammar` +# +# Pros: +# +# - no generated file commited +# - easier to modify and bootstrap +# +# Cons: +# +# - somewhat dublicate the ful grammar of nitcc +# - need an ad-hoc lexer (nitcc_lexer0.nit) +# +module nitcc_parser_gen + +import grammar + +var g = new Gram +var p_gr = new Production("grammar") +var p_lex = new Production("lexer") +var p_exprs = new Production("exprs") +var p_expr = new Production("expression") +var p_re = new Production("re") +var p_re1 = new Production("re1") +var p_re2 = new Production("re2") +var p_re3 = new Production("re3") +var p_par = new Production("parser") +var p_ign = new Production("ignored") +var p_prods = new Production("prods") +var p_prod = new Production("production") +var p_ptrans_o = new Production("ptrans_o") +var p_alts = new Production("alts") +var p_alt = new Production("alternative") +var p_altid_o = new Production("altid_o") +var p_altid = new Production("altident") +var p_elems = new Production("elems") +var p_elem = new Production("elem") +g.prods.add_all([p_gr, p_re, p_re1, p_re2, p_re3, p_lex, p_exprs, p_expr, p_par, p_ign, p_prods, p_prod, p_ptrans_o, p_alts, p_alt, p_altid_o, p_altid, p_elems, p_elem]) +g.prods.add(new Production("atrans")) +g.prods.add(new Production("elemid")) +g.prods.add(new Production("nelem")) + +var t_opar = new Token("opar") +var t_cpar = new Token("cpar") +var t_ocur = new Token("ocur") +var t_ccur = new Token("ccur") +var t_pipe = new Token("pipe") +var t_star = new Token("star") +var t_ques = new Token("ques") +var t_plus = new Token("plus") +var t_minus = new Token("minus") +var t_colo = new Token("colo") +var t_semi = new Token("semi") +var t_dot = new Token("dot") +var t_eq = new Token("eq") +var t_arrow = new Token("arrow") +var t_str = new Token("str") +var t_id = new Token("id") +var t_kw = new Token("kw") +var t_any = new Token("any") +var t_ch_dec = new Token("ch_dec") +g.tokens.add_all([t_opar, t_cpar, t_ocur, t_ccur, t_pipe, t_star, t_ques, t_plus, t_minus, t_colo, t_semi, t_dot, t_eq, t_arrow, t_str, t_id, t_kw, t_any, t_ch_dec]) + +p_gr.new_alt("gr", t_kw, t_id, t_semi, p_lex, p_par) + +p_lex.new_alt("lex", t_kw, p_exprs) + +p_exprs.new_alt("exprs_many", p_exprs, p_expr) +p_exprs.new_alt0("exprs_none") + +p_expr.new_alt("expr", t_id, t_eq, p_re, t_semi) + +p_re.new_alt("re_alter", p_re, t_pipe, p_re1) +p_re.new_alt("re_re2", p_re1) + +p_re1.new_alt("re_minus", p_re1, t_minus, p_re2) +p_re1.new_alt("re_re1", p_re2) + +p_re2.new_alt("re_conc", p_re2, p_re3) +p_re2.new_alt("re_re3", p_re3) + +p_re3.new_alt("re_star", p_re3, t_star) +p_re3.new_alt("re_ques", p_re3, t_ques) +p_re3.new_alt("re_plus", p_re3, t_plus) +p_re3.new_alt("re_par", t_opar, p_re, t_cpar) +p_re3.new_alt("re_str", t_str) +p_re3.new_alt("re_ch_dec", t_ch_dec) +p_re3.new_alt("re_class", t_str, t_dot, t_dot, t_str) +p_re3.new_alt("re_any", t_any) +p_re3.new_alt("re_id", t_id) + +p_par.new_alt("par", t_kw, p_ign, p_prods) + +p_ign.new_alt0("ign_none") +p_ign.new_alt("ign", t_kw, t_id, t_semi) + +p_prods.new_alt("prods_many", p_prods, p_prod) +p_prods.new_alt0("prods_none") + +p_prod.new_alt("prod", t_id, p_ptrans_o, t_eq, p_alts, t_semi) + +p_ptrans_o.new_alt("ptrans", t_ocur, t_arrow, t_id, t_ccur) +p_ptrans_o.new_alt0("ptrans_none") + +p_alts.new_alt("alts_many", p_alts, t_pipe, p_alt) +p_alts.new_alt("alts_one", p_alt) + +p_alt.new_alt("alt", p_altid_o, p_elems) + +p_altid_o.new_alt0("altid_o_none") +p_altid_o.new_alt("altid_o_one", p_altid) + +p_altid.new_alt("altid", t_ocur, t_id, t_colo, t_ccur) + +p_elems.new_alt("elems_many", p_elems, p_elem) +p_elems.new_alt0("elems_none") + +p_elem.new_alt("elem_id", t_id) +p_elem.new_alt("elem_str", t_str) +p_elem.new_alt("elem_par", t_opar, p_alts, t_cpar) +p_elem.new_alt("elem_star", p_elem, t_star) +p_elem.new_alt("elem_ques", p_elem, t_ques) +p_elem.new_alt("elem_plus", p_elem, t_plus) + +var a = g.lr0 + +print "LR automaton: {a.states.length} states (see nitcc0.lr.dot)" +a.to_dot("nitcc0.lr.dot") + +a.gen_to_nit("nitcc_parser.nit") + +var f = new OFStream.open("nitcc_lexer.nit") +f.write("import nitcc_lexer0\n") +f.close diff --git a/contrib/nitcc/nitcc_runtime.nit b/contrib/nitcc/nitcc_runtime.nit new file mode 100644 index 0000000..5778641 --- /dev/null +++ b/contrib/nitcc/nitcc_runtime.nit @@ -0,0 +1,543 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Runtime library required by parsers and lexers generated by nitcc +module nitcc_runtime + +# A abstract parser engine generated by nitcc +abstract class Parser + # The list of tokens + # FIXME: provide something better, like a lexer? + var tokens = new List[NToken] + + # Look at the next token + # Used by generated parsers + fun peek_token: NToken do return tokens.first + + # Consume the next token + # Used by generated parsers + fun get_token: NToken do return tokens.shift + + # Consume the next token and shift to the state `dest`. + # Used by generated parsers + fun shift(dest: LRState) + do + var t = get_token + #print "shift {t} -> {dest}" + node_stack.push t + state_stack.push state + state = dest + end + + # After a reduction on `goto` go to the next state + # Used by generated parsers + fun goto(goto: LRGoto) + do + #print "reduce from {state} -> {prod}" + state.goto(self, goto) + end + + # push a new state on the stack of states ( + # Used by generated parsers + fun push(dest: LRState) + do + #print "push prod {prod} -> {dest}" + state_stack.push state + state = dest + end + + # Pop and return the last node + # Also pop (and discard) the associated state + # Used by generated parsers + fun pop: Node + do + var res = node_stack.pop + state = state_stack.pop + return res + end + + # Produce a parse error and stop the parsing + # Used by generated parsers + fun parse_error + do + var token = peek_token + print "* parse error in state {state} on token {token}" + print " expected: {state.error_msg}" + print " node_stack={node_stack.join(", ")}" + print " state_stack={state_stack.join(", ")}" + var error: Node + if token isa NLexerError then + error = token + token.error_tree.items.add_all(node_stack) + else + error = new NParserError + error.position = token.position + error.text = token.text + error.token = token + error.error_tree.items.add_all(node_stack) + end + node_stack.clear + node_stack.add error + stop = true + end + + # The stating state for parsing + # Used by generated parsers + protected fun start_state: LRState is abstract + + # The current state + # Used by generated parsers + var state: LRState + + init + do + state = start_state + end + + # The stack of nodes + # Used by generated parsers + var node_stack = new Array[Node] + + # The stack of states + # Used by generated parsers + var state_stack = new Array[LRState] + + # Should the parser stop + # Used by generated parsers + var stop writable = true + + # Parse a full sequence of tokens and return a complete syntactic tree + fun parse: Node + do + state = start_state + state_stack.clear + node_stack.clear + stop = false + while not stop do + #print "* current state {state}" + #print " tokens={tokens.join(" ")}" + #print " node_stack={node_stack.join(" ")}" + #print " state_stack={state_stack.join(" ")}" + state.action(self) + end + #print "* over" + return node_stack.first + end +end + +# A state in a parser LR automaton generated by nitcc +# Used by generated parsers +abstract class LRState + fun action(parser: Parser) is abstract + fun goto(parser: Parser, goto: LRGoto) is abstract + fun error_msg: String do return "FIXME" +end + +# A concrete production in a parser LR automation generated by nitcc +# Used by generated parsers +abstract class LRGoto +end + +### + +# A abstract lexer engine generated by nitcc +abstract class Lexer + # The input stream of characters + var stream: String + + # The stating state for lexing + # Used by generated parsers + protected fun start_state: DFAState is abstract + + # Lexize a stream of characters and return a sequence of tokens + fun lex: List[NToken] + do + var res = new List[NToken] + var state = start_state + var pos = 0 + var pos_start = 0 + var pos_end = 0 + var line = 1 + var line_start = 1 + var line_end = 0 + var col = 1 + var col_start = 1 + var col_end = 0 + var last_state: nullable DFAState = null + var text = stream + var length = text.length + loop + if state.is_accept then + pos_end = pos - 1 + line_end = line + col_end = col + last_state = state + end + var c + if pos >= length then + c = '\0' + else + c = text[pos] + end + var next = state.trans(c) + if next == null then + if last_state == null then + var token = new NLexerError + var position = new Position(pos_start, pos, line_start, line, col_start, col) + token.position = position + token.text = text.substring(pos_start, pos-pos_start+1) + res.add token + break + end + var position = new Position(pos_start, pos_end, line_start, line_end, col_start, col_end) + var token = last_state.make_token(position, text.substring(pos_start, pos_end-pos_start+1)) + if token != null then res.add(token) + if pos >= length then + token = new NEof + position = new Position(pos, pos, line, line, col, col) + token.position = position + token.text = "" + res.add token + break + end + state = start_state + pos_start = pos_end + 1 + pos = pos_start + line_start = line_end + line = line_start + col_start = col_end + col = col_start + + last_state = null + continue + end + state = next + pos += 1 + col += 1 + if c == '\n' then + line += 1 + col = 1 + end + end + return res + end +end + +# A state in a lexer automaton generated by nitcc +# Used by generated lexers +interface DFAState + fun is_accept: Bool do return false + fun trans(c: Char): nullable DFAState do return null + fun make_token(position: Position, text: String): nullable NToken is abstract +end + +### + +# A abstract visitor on syntactic trees generated by nitcc +abstract class Visitor + # The main entry point to visit a node `n` + # Should not be redefined + fun enter_visit(n: Node) + do + visit(n) + end + + # The specific implementation of a visit + # + # Should be redefined by concrete visitors + # + # Should not be called directly (use `enter_visit` instead) + # + # By default, the visitor just rescursively visit the children of `n` + protected fun visit(n: Node) + do + n.visit_children(self) + end +end + +# Print a node (using to_s) on a line and recustively each children indented (with two spaces) +class TreePrinterVisitor + super Visitor + var writer: OStream + private var indent = 0 + init(writer: OStream) do self.writer = writer + redef fun visit(n) + do + for i in [0..indent[ do writer.write(" ") + writer.write(n.to_s) + writer.write("\n") + indent += 1 + super + indent -= 1 + end +end + +# A position into a input stream +# Used to give position to tokens +class Position + var pos_start: Int + var pos_end: Int + var line_start: Int + var line_end: Int + var col_start: Int + var col_end: Int + redef fun to_s do return "{line_start}:{col_start}-{line_end}:{col_end}" +end + +# A node of a syntactic tree +abstract class Node + # The name of the node (as used in the grammar file) + fun node_name: String do return class_name + + # A point of view on the direct childrens of the node + fun children: SequenceRead[nullable Node] is abstract + + # Visit all the children of the node with the visitor `v` + protected fun visit_children(v: Visitor) + do + for c in children do if c != null then v.enter_visit(c) + end + + # The position of the node in the input stream + var position: nullable Position writable = null + + # Produce a graphiz file for the syntaxtic tree rooted at `self`. + fun to_dot(filepath: String) + do + var f = new OFStream.open(filepath) + f.write("digraph g \{\n") + f.write("rankdir=BT;\n") + + var a = new Array[NToken] + to_dot_visitor(f, a) + + f.write("\{ rank=same\n") + var first = true + for n in a do + if first then + first = false + else + f.write("->") + end + f.write("n{n.object_id}") + end + f.write("[style=invis];\n") + f.write("\}\n") + + f.write("\}\n") + f.close + end + + private fun to_dot_visitor(f: OStream, a: Array[NToken]) + do + f.write("n{object_id} [label=\"{node_name}\"];\n") + for x in children do + if x == null then continue + f.write("n{x.object_id} -> n{object_id};\n") + x.to_dot_visitor(f,a ) + end + end + + redef fun to_s do + var pos = position + if pos == null then + return "{node_name}" + else + return "{node_name}@({pos})" + end + end +end + +# A token produced by the lexer and used in a syntactic tree +abstract class NToken + super Node + + redef fun children do return once new Array[Node] + + redef fun to_dot_visitor(f, a) + do + var labe = "{node_name}" + var pos = position + if pos != null then labe += "\\n{pos}" + var text = self.text + if node_name != "'{text}'" then + labe += "\\n'{text.escape_to_c}'" + end + f.write("n{object_id} [label=\"{labe}\",shape=box];\n") + a.add(self) + end + + # The text associated with the token + var text: String writable = "" + + redef fun to_s do + var res = super + var text = self.text + if node_name != "'{text}'" then + res += "='{text.escape_to_c}'" + end + return res + end +end + +# The special token for the end of stream +class NEof + super NToken +end + +# A special token used to represent a parser or lexer error +abstract class NError + super NToken + + # All the partially built tree during parsing (aka the node_stack) + var error_tree = new Nodes[Node] +end + +# A lexer error as a token for the unexpected characted +class NLexerError + super NError +end + +# A parser error linked to a unexpected token +class NParserError + super NError + # The unexpected token + var token: nullable NToken +end + +# A hogeneous sequence of node, used to represent unbounded lists (and + modifier) +class Nodes[T: Node] + super Node + redef fun children do return items + var items = new Array[T] +end + +# A production with a specific, named and statically typed childrens +class NProd + super Node + redef var children: SequenceRead[nullable Node] = new NProdChildren(self) + + # The exact number of direct children + # Used to implement `children` by generated parsers + fun number_of_children: Int is abstract + + # The specific children got by its index + # Used to implement `children` by generated parsers + fun child(x: Int): nullable Node is abstract +end + + +private class NProdChildren + super SequenceRead[nullable Node] + var prod: NProd + redef fun iterator do return new NProdIterator(prod) + redef fun length do return prod.number_of_children + redef fun is_empty do return prod.number_of_children == 0 + redef fun [](i) do return prod.child(i) +end + +private class NProdIterator + super IndexedIterator[nullable Node] + var prod: NProd + redef var index = 0 + redef fun is_ok do return index < prod.number_of_children + redef fun next do index += 1 + redef fun item do return prod.child(index) +end + +# All-in-one abstract class to test generated parsers on a given +abstract class TestParser + # How to get a new lexer on a given stream of character + fun new_lexer(text: String): Lexer is abstract + + # How to get a new parser + fun new_parser: Parser is abstract + + # The name of the language (used for generated files) + fun name: String is abstract + + # Use the class as the main enrty point of the program + # - parse arguments and options of the command + # - test the parser (see `work`) + fun main: Node + do + if args.is_empty then + print "usage {name}_test | - | -e " + exit 0 + end + + var filepath = args.shift + var text + if filepath == "-" then + text = stdin.read_all + else if filepath == "-e" then + if args.is_empty then + print "Error: -e need a text" + exit 1 + end + text = args.shift + else + var f = new IFStream.open(filepath) + text = f.read_all + f.close + end + + if not args.is_empty then + print "Error: superfluous arguments." + exit 1 + end + + return work(text) + end + + # Produce a full syntactic tree for a given stream of character + # Produce also statistics and output files + fun work(text: String): Node + do + print "INPUT: {text.length} chars" + var l = new_lexer(text) + var tokens = l.lex + + var tokout = "{name}.tokens.out" + print "TOKEN: {tokens.length} tokens (see {tokout})" + + var f = new OFStream.open(tokout) + for t in tokens do + f.write "{t.to_s}\n" + end + f.close + + var p = new_parser + p.tokens.add_all(tokens) + + var n = p.parse + + var astout = "{name}.ast.out" + f = new OFStream.open(astout) + var tpv = new TreePrinterVisitor(f) + var astdotout = "{name}.ast.dot" + if n isa NError then + print "ERROR: {n} (see {astout} and {astdotout})" + tpv.enter_visit(n) + n = n.error_tree + else + print "ROOT: {n} (see {astout} and {astdotout})" + end + tpv.enter_visit(n) + n.to_dot(astdotout) + f.close + + return n + end +end diff --git a/contrib/nitcc/nitcc_semantic.nit b/contrib/nitcc/nitcc_semantic.nit new file mode 100644 index 0000000..8713da0 --- /dev/null +++ b/contrib/nitcc/nitcc_semantic.nit @@ -0,0 +1,487 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Semantic analysis of a sablecc grammar file +# User to validate the file and generate the grammar and the nfa +# +# TODO: split in submodules +module nitcc_semantic + +import nitcc_parser +import grammar +import re2nfa + +# Main visitor for the semantic analysis +# +# TODO clean-up the visitors +class CollectNameVisitor + super Visitor + + var nprods = new Array[Nprod] + + # Symbol table to associate things (prods and exprs) with their name + var names = new HashMap[String, Node] + + # The associated grammar object + # Read the result of the visit here + var gram = new Gram + + # The associated NFA object + # Read the result of the visit here + var nfa = new Automaton.empty + + # Run the semantic analysis of the grammar + fun start(n: Node) + do + # First visit to collect names + enter_visit(n) + + # Second visit to use collectec names and build rhings + var v2 = new CheckNameVisitor(self) + v2.enter_visit(n) + + # Inline all the ? + gram.inline(v2.quesizes.values) + # Inlile all the prods sufixed by '_imline' #TODO use a real keyword + for p in gram.prods do + if not p.name.has_suffix("_inline") then continue + print "inline {p}" + gram.inline([p]) + end + + # Build the NFA automaton + for t in gram.tokens do + var nexpr = t.nexpr + var nfa2 + if nexpr == null then + nfa2 = new Automaton.epsilon + for c in t.text.as(not null) do + nfa2.concat(new Automaton.atom(c.ascii)) + end + else + nfa2 = nexpr.build_nfa + end + nfa.states.add_all nfa2.states + nfa.start.add_trans(nfa2.start, null) + for s in nfa2.accept do nfa.add_tag(s, t) + nfa.accept.add_all nfa2.accept + end + end + + redef fun visit(n) do n.accept_collect_prod(self) +end + +private class CheckNameVisitor + super Visitor + + # The collected altname, for the alternative + var altname: nullable String = null + + # The collected elements, for the alternative + var elems = new Array[Element] + + # The collected element names, for the alternative + var elems_names = new Array[nullable String] + + # The collected elementname, for the nelem + var elemname: nullable String = null + + # Is the alternative transformed, for the alternative + var trans = false + + # Pool of elements that are modified with + (reuse them!) + private var plusizes = new HashMap[Element, Production] + + # Create a + version of an element + fun plusize(e: Element): Production + do + if plusizes.has_key(e) then return plusizes[e] + var name = "{e}+" + var prod = new Production(name) + prod.acname = "Nodes[{e.acname}]" + v1.gram.prods.add(prod) + prod.new_alt("{name}_one", e) + prod.new_alt("{name}_more", prod, e) + plusizes[e] = prod + return prod + end + + # Pool of elements that are modified with ? (reuse them!) + private var quesizes = new HashMap[Element, Production] + + # Create a ? version of an element + fun quesize(e: Element): Production + do + if quesizes.has_key(e) then return quesizes[e] + var name = "{e}?" + var prod = new Production(name) + prod.acname = "nullable {e.acname}" + v1.gram.prods.add(prod) + var a1 = prod.new_alt("{name}_one", e) + a1.codes = [new CodePop] + var a0 = prod.new_alt0("{name}_none") + a0.codes = [new CodeNull] + quesizes[e] = prod + return prod + end + + # The current nexpr, used to track dependency on named expressions (see `Nexpr::precs`) + var nexpr: nullable Nexpr + + # The current production, used to initialize alternatives + var prod: nullable Production + + # The main visitor, used to access the grammar of the symbol table + var v1: CollectNameVisitor + init(v1: CollectNameVisitor) do self.v1 = v1 + + redef fun visit(n) do n.accept_check_name_visitor(self) +end + +redef class Node + private fun accept_collect_prod(v: CollectNameVisitor) do visit_children(v) + private fun accept_check_name_visitor(v: CheckNameVisitor) do visit_children(v) +end + +redef class Nexpr + # The associated token + var token: nullable Token + + # The associated name + var name: nullable String + + # The required expression (Nexpr that are used inside) + var precs = new ArraySet[Nexpr] + + redef fun accept_collect_prod(v) do + var id = children.first.as(Nid) + var name = id.text + v.names[name] = self + self.name = name + end + redef fun accept_check_name_visitor(v) do + v.nexpr = self + super + v.nexpr = null + end + + # Flag to track circular regular expression + var is_building = false + + # The associated NFA (cached, see `build_nfa`) + private var nfa: nullable Automaton + + # Build the NFA, possibily building the NFA of required expressions + # Print an error if there is a circular dependency + # The result is cached + fun build_nfa: Automaton do + var res = nfa + if res != null then return res + if is_building then + print "Error: circular regular expression {name.to_s}." + exit(1) + abort + end + is_building = true + for p in precs do + p.build_nfa + end + is_building = false + var nre = self.children[2] + res = nre.make_rfa + nfa = res + return res + end +end + +redef class Nre_id + # The named expression + var nexpr: nullable Nexpr + + redef fun accept_check_name_visitor(v) do + var id = children.first.as(Nid) + var name = id.text + if not v.v1.names.has_key(name) then + print "Error: unknown name {name}" + exit(1) + abort + end + var node = v.v1.names[name] + if node isa Nprod then + print "Error: cannot use production {name} in a regular expression" + exit(1) + abort + else if not node isa Nexpr then + abort + end + nexpr = node + v.nexpr.precs.add(node) + end + + redef fun make_rfa + do + return nexpr.nfa.dup + end +end + +redef class Nign + # The named element + var elem: nullable Element + + redef fun accept_check_name_visitor(v) do + var id = children[1].as(Nid) + var name = id.text + if not v.v1.names.has_key(name) then + print "Error: unknown name {name}" + exit(1) + abort + end + var node = v.v1.names[name] + var elem: nullable Element + if node isa Nprod then + print "Error cannot ignore a production" + exit(1) + abort + else if node isa Nexpr then + elem = node.token + if elem == null then + elem = new Token("Ignored") + elem.nexpr = node + v.v1.gram.tokens.add(elem) + node.token = elem + end + else + abort + end + self.elem = elem + end +end + +redef class Nprod + # The associated production + var prod: nullable Production + + redef fun accept_collect_prod(v) do + var id = children.first.as(Nid) + var name = id.text + v.names[name] = self + v.nprods.add(self) + prod = new Production(name) + v.gram.prods.add(prod.as(not null)) + end + redef fun accept_check_name_visitor(v) do + v.prod = prod + super + v.prod = null + end +end + +redef class Nptrans + redef fun accept_check_name_visitor(v) do + var id = children[2].as(Nid) + var name = id.text + + var node = v.v1.names[name] + if node isa Nprod then + v.prod.spe = node.prod.as(not null) + if v.prod.spe.spe != null then + print "Cannot transform into {name}, {name} is already transformed." + exit(1) + abort + end + else if node isa Nexpr then + print "Cannot transform into {name}, {name} is a token." + else + abort + end + end +end + +redef class Natrans + redef fun accept_check_name_visitor(v) do + var id = children[2].as(Nid) + var name = id.text + + v.trans = true + end +end + +redef class Nalt + # The associated alternative + var alt: nullable Alternative + + redef fun accept_check_name_visitor(v) + do + v.altname = null + v.trans = false + v.elems = new Array[Element] + v.elems_names = new Array[nullable String] + super + var prod = v.prod.as(not null) + var prodabs = prod.spe + if prodabs == null then prodabs = prod + var name = v.altname + if name == null then + if v.trans then + name = prod.name + "_" + prod.alts.length.to_s + else if prod.spe == null and prod.alts.is_empty then + name = prod.name + prod.altone = true + else + if prodabs.altone then + prodabs.altone = false + prodabs.alts.first.name = prodabs.name + "_0" + end + name = prod.name + "_" + prod.alts.length.to_s + end + else + if prodabs.altone then + prodabs.altone = false + prodabs.alts.first.name = prodabs.name + "_0" + end + name = prodabs.name + "_" + name + end + var alt = prod.new_alt2(name, v.elems) + alt.elems_names.add_all(v.elems_names) + self.alt = alt + if v.trans then + alt.trans = true + alt.codes = [new CodePop] + end + end +end + +redef class Naltid + redef fun accept_check_name_visitor(v) + do + var id = children[1].as(Nid) + var name = id.text + v.altname = name + end +end + +redef class Nelem + # The associated element + var elem: nullable Element +end + +redef class Token + # The associated expression (if any, ie defined in the lexer part) + var nexpr: nullable Nexpr + # The associated text (if any, ie defined in the parser part) + var text: nullable String +end + +redef class Nnelem + redef fun accept_check_name_visitor(v) + do + v.elemname = null + super + var elemname = v.elemname + if elemname != null and v.elems_names.has(elemname) then + var i = 2 + while v.elems_names.has(elemname+i.to_s) do i += 1 + elemname = elemname+i.to_s + end + v.elems_names.add elemname + end +end + +redef class Nelemid + redef fun accept_check_name_visitor(v) + do + var id = children[1].as(Nid) + var name = id.text + v.elemname = name + end +end + +redef class Nelem_id + redef fun accept_check_name_visitor(v) do + var id = children.first.as(Nid) + var name = id.text + if not v.v1.names.has_key(name) then + print "Error: unknown name {name}" + exit(1) + abort + end + var node = v.v1.names[name] + var elem: nullable Element + if node isa Nprod then + elem = node.prod + else if node isa Nexpr then + elem = node.token + if elem == null then + elem = new Token(name) + elem.nexpr = node + v.v1.gram.tokens.add(elem) + node.token = elem + end + else + abort + end + assert elem != null + self.elem = elem + v.elems.add(elem) + if v.elemname == null then v.elemname = name + end +end + +redef class Nelem_str + redef fun accept_check_name_visitor(v) do + var str = children.first.as(Nstr) + var text = str.value + var name = str.text + var elem: nullable Element + if v.v1.names.has_key(name) then + elem = v.v1.names[name].as(Nelem_str).elem + assert elem != null + else + elem = new Token(name) + elem.text = text + v.v1.gram.tokens.add(elem) + v.v1.names[name] = self + end + self.elem = elem + v.elems.add(elem) + end +end + +redef class Nelem_star + redef fun accept_check_name_visitor(v) do + super + var elem = v.elems.pop + elem = v.plusize(elem) + elem = v.quesize(elem) + v.elems.add elem + end +end + +redef class Nelem_ques + redef fun accept_check_name_visitor(v) do + super + var elem = v.elems.pop + elem = v.quesize(elem) + v.elems.add elem + end +end + +redef class Nelem_plus + redef fun accept_check_name_visitor(v) do + super + var elem = v.elems.pop + elem = v.plusize(elem) + v.elems.add elem + end +end diff --git a/contrib/nitcc/re2nfa.nit b/contrib/nitcc/re2nfa.nit new file mode 100644 index 0000000..9a4008d --- /dev/null +++ b/contrib/nitcc/re2nfa.nit @@ -0,0 +1,153 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Transformation of regular expression to NFA +module re2nfa + +import nitcc_lexer +import autom + +redef class Node + # Build the NFA of the regular expression + fun make_rfa: Automaton do + print inspect + abort + end +end + +redef class Nstr + # The real value of the string + fun value: String do return text.substring(1, text.length-2).unescape_nit + redef fun make_rfa: Automaton + do + var a = new Automaton.epsilon + var val + for c in self.value do + var b = new Automaton.atom(c.ascii) + a.concat(b) + end + return a + end +end + +redef class Nch_dec + # The real value of the char + fun value: String do return text.substring_from(1).to_i.ascii.to_s + redef fun make_rfa: Automaton + do + var a = new Automaton.atom(self.value.first.ascii) + return a + end +end + +redef class NProd + redef fun make_rfa: Automaton + do + assert children.length == 1 else print "no make_rfa for {self}" + return children.first.make_rfa + end +end + +redef class Nre_alter + redef fun make_rfa + do + var a = children[0].make_rfa + var b = children[2].make_rfa + a.alternate(b) + return a + end +end + +redef class Nre_minus + redef fun make_rfa + do + var a = children[0].make_rfa + var b = children[2].make_rfa.to_dfa + for t in b.start.outs do + if not t.to.outs.is_empty then + print "Not Yet Implemented Error: '-' only works on single char" + exit(1) + end + a.minus_sym(t.symbol.as(not null)) + end + return a + end +end + +redef class Nre_conc + redef fun make_rfa + do + var a = children[0].make_rfa + var b = children[1].make_rfa + a.concat(b) + return a + end +end + +redef class Nre_star + redef fun make_rfa + do + var a = children[0].make_rfa + a.close + return a + end +end + +redef class Nre_ques + redef fun make_rfa + do + var a = children[0].make_rfa + a.optionnal + return a + end +end + +redef class Nre_plus + redef fun make_rfa + do + var a = children[0].make_rfa + a.plus + return a + end +end + +redef class Nre_par + redef fun make_rfa + do + return children[1].make_rfa + end +end + +redef class Nre_class + redef fun make_rfa: Automaton + do + var c1 = children[0].as(Nstr).value + var c2 = children[3].as(Nstr).value + if c1.length != 1 or c2.length != 1 then + print "Classes only works on single char" + exit(1) + abort + end + var a = new Automaton.cla(c1.first.ascii, c2.first.ascii) + return a + end +end + +redef class Nre_any + redef fun make_rfa: Automaton + do + var a = new Automaton.cla(0, 127) + return a + end +end diff --git a/contrib/nitcc/t/alterner.pl b/contrib/nitcc/t/alterner.pl new file mode 100755 index 0000000..af66c96 --- /dev/null +++ b/contrib/nitcc/t/alterner.pl @@ -0,0 +1,186 @@ +#!/usr/bin/perl + +# Alterner.pl +# +# Copyright 2011 Jean Privat +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use strict; +use File::Basename; + +# Default values for options +my $directory = "alt"; # The directory where alternatives will be generated. +my $start = "//"; # The marker at the begin of a directive (usually the start of a comment). +my $end = ""; # The marker at the end of the line (usually the end of a comment) +my $altsep = "."; # The separator used in generated file between the basename and the altmark. + +sub usage(;$) { + my $msg = shift; + my $usage = "Usage: alterner.pl [-d dir] [--start pat] [--end pat] file..."; + if (defined $msg) { + print STDERR $msg . "\n" . $usage . "\n"; + exit 1; + } else { + print $usage . "\n"; + exit 0; + } +} + +# Process arguments. +my $stop = 0; +while (@ARGV && !$stop) { + my $arg = $ARGV[0]; + my $val = $ARGV[1]; + if ($arg eq "-d") { + $directory = $val or usage "$arg requires a directory."; + shift @ARGV; + shift @ARGV; + } elsif ($arg eq "--start") { + $start = $val or usage "$arg requires a pattern."; + shift @ARGV; + shift @ARGV; + } elsif ($arg eq "--end") { + $end = $val or usage "$arg requires a pattern."; + shift @ARGV; + shift @ARGV; + } elsif ($arg eq "--altsep") { + $altsep = $val or usage "$arg requires a pattern."; + shift @ARGV; + shift @ARGV; + } elsif ($arg eq "-h" || $arg eq "--help") { + shift @ARGV; + usage + } elsif ($arg eq "--") { + shift @ARGV; + $stop = 1; + } elsif ($arg =~ /^-/) { + usage "Unknown argument $arg."; + } else { + $stop = 1; + } +} + +if ($#ARGV == -1) { + usage("No input file."); +} + +# Is $_[0] triggers the alternative directive $[1]? +sub triggers_alt($$) { + my $number = shift; + my $directive = shift; + foreach my $a (split ",", $directive) { + if ($a =~ /^(\d+)-(\d+)$/) { + if ($1 <= $number && $number <= $2) { + return 1; + } + } else { + if ($number == $a) { + return 1; + } + } + } + return 0; +} + +# Generate alternatives from the specified input-file using a specific altmark +sub process_alts($$) { + my $file = shift; + my $altmark = shift; + # Read the file + open my $in, "<", $file or die "$file: $!"; + my @lines = <$in>; + close($file); + + my $prefix = $start . $altmark; + + # Collect alternatives + my %alt; + foreach my $l (@lines) { + while ($l =~ /\Q$prefix\E([\d,-]+)(\Q$start\E|\b)/g) { + for my $a (split /[,-]/, $1) { + $alt{$a} = 1; + } + } + } + my @alt = sort(keys(%alt)); + + my @files; + # Process each alternatives + foreach my $alt (@alt) { + # Exctact the basename and the suffix + my ($name, $path, $suffix) = fileparse($file, qr/\.[^\.]*/); + + # Compute filename of the alternative + my $outfile = $name . $altsep . $altmark . $alt . $suffix; + if (defined $directory && $directory ne ".") { + $outfile = $directory . "/" . $outfile; + if (! -d $directory) { + mkdir $directory or die "$directory: $!"; + } + } + push @files, $outfile; + + # Write the alternative + open my $out, ">", $outfile or die "$outfile: $!"; + print "$outfile\n"; + foreach my $l (@lines) { + my $l2 = $l; + my $selected; + while ($l =~ /(\Q$prefix\E([\d,-]+)(\Q$start\E|\b))/g) { + if (triggers_alt $alt, $2) { + $selected = $1; + } + } + if ($selected && $l =~ /^(\s*)(.*)(\s*)(\Q$selected\E)([ \t]*)(.*)([ \t]*\Q$end\E\s*)$/) { + $l2 = "$1$6$3$4$5$2$7"; + } + print $out $l2 or die "$outfile: $!"; + } + close $out; + } + return @files; +} + +# Generate combination of alternatives from the specified input-file +sub process_xalts($) { + my $file = shift; + # Read the file + open my $in, "<", $file or die "$file: $!"; + my @lines = <$in>; + close($file); + + # Collect combination of alternatives + my %alt; + foreach my $l (@lines) { + while ($l =~ /\Q$start\E(\d*alt)\d+(\Q$start\E|\b)/g) { + $alt{$1} = $1; + } + } + my @alt = sort(keys(%alt)); + + my @files = $file; + # Process each combination of alternatives + foreach my $alt (@alt) { + my @newfiles; + foreach my $f (@files) { + push @newfiles, process_alts($f, $alt); + } + push @files, @newfiles; + } +} + +# Do the job +foreach my $file (@ARGV) { + process_xalts($file); +} diff --git a/contrib/nitcc/t/empty.input b/contrib/nitcc/t/empty.input new file mode 100644 index 0000000..2e65efe --- /dev/null +++ b/contrib/nitcc/t/empty.input @@ -0,0 +1 @@ +a \ No newline at end of file diff --git a/contrib/nitcc/t/empty.input2 b/contrib/nitcc/t/empty.input2 new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/empty.sablecc b/contrib/nitcc/t/empty.sablecc new file mode 100644 index 0000000..bab61e3 --- /dev/null +++ b/contrib/nitcc/t/empty.sablecc @@ -0,0 +1,15 @@ +//alt1 /* +Grammar x; +//alt2 /* +Lexer +//alt3 /* +a = 'a'; +//alt4 /* +Parser +//alt5 /* +Ignored a; +//alt6 /* +p = a; + +/* //alt1 //alt2 //alt3 //alt4 //alt5 //alt6 +*/ diff --git a/contrib/nitcc/t/if.sablecc b/contrib/nitcc/t/if.sablecc new file mode 100644 index 0000000..374f2dd --- /dev/null +++ b/contrib/nitcc/t/if.sablecc @@ -0,0 +1,15 @@ +Grammar if; +Lexer +Parser + +p = 'e' e | 'f' f; + +e = + 'if' e 'then' e else? | + 'e' ; +else = 'else' e; + +f = + 'if' f 'then' f | + 'if' f 'then' f 'else' f | + 'f' ; diff --git a/contrib/nitcc/t/inf5000-04-lexer-automate.input b/contrib/nitcc/t/inf5000-04-lexer-automate.input new file mode 100644 index 0000000..6c2d35a --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-automate.input @@ -0,0 +1,9 @@ +if iff iff i f +if50i +if 50 i +50 +50.50 +50. +.50 +50.f +f.50 diff --git a/contrib/nitcc/t/inf5000-04-lexer-automate.sablecc b/contrib/nitcc/t/inf5000-04-lexer-automate.sablecc new file mode 100644 index 0000000..a06bd38 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-automate.sablecc @@ -0,0 +1,14 @@ +Grammar automate; +Lexer + letter = 'a'..'z'; + digit = '0'..'9'; + id = letter(letter|digit)*; + if = 'if'; + int = (digit)+; + float = (digit)+ '.' (digit)+; + dot = '.'; + blank = #10|#13|#32; +Parser + Ignored blank; + p = t*; + t = id | if | int | float | dot; diff --git a/contrib/nitcc/t/inf5000-04-lexer-demo.input b/contrib/nitcc/t/inf5000-04-lexer-demo.input new file mode 100644 index 0000000..a6d7966 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-demo.input @@ -0,0 +1,3 @@ +if iff iff i f +if50i +if,i diff --git a/contrib/nitcc/t/inf5000-04-lexer-demo.input2 b/contrib/nitcc/t/inf5000-04-lexer-demo.input2 new file mode 100644 index 0000000..e373ee6 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-demo.input2 @@ -0,0 +1 @@ +50 diff --git a/contrib/nitcc/t/inf5000-04-lexer-demo.sablecc b/contrib/nitcc/t/inf5000-04-lexer-demo.sablecc new file mode 100644 index 0000000..42a7671 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-demo.sablecc @@ -0,0 +1,14 @@ +Grammar demo; +Lexer + letter = 'a'..'z'; + digit = '0'..'9'; + identifier = letter (letter | digit)*; + comma = ','; + blank = (' ' | #9 | #10 | #13)+; + if = 'if'; + else = 'else'; +Parser + Ignored + blank; + p = t*; + t = identifier | comma | if | else; diff --git a/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input new file mode 100644 index 0000000..0601475 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab diff --git a/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input2 b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input2 new file mode 100644 index 0000000..2abac58 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.input2 @@ -0,0 +1 @@ +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/contrib/nitcc/t/inf5000-04-lexer-pire_cout.sablecc b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.sablecc new file mode 100644 index 0000000..841d90a --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-pire_cout.sablecc @@ -0,0 +1,9 @@ +Grammar pire_cout; +Lexer + a = 'a'; + b = 'a'* 'b'; +blank = ' ' | #9 | #10 | #13; +Parser + Ignored blank; + p = t*; + t = a | b; diff --git a/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.input b/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.input new file mode 100644 index 0000000..41a8a53 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.input @@ -0,0 +1,3 @@ +i f +if +ify diff --git a/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.sablecc b/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.sablecc new file mode 100644 index 0000000..7b50dfc --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-priorite_d_inclusion.sablecc @@ -0,0 +1,9 @@ +Grammar priorite_d_inclusion; +Lexer + identifier = ('a'..'z')+; + if = 'if'; + blank = ' ' | #9 | #10 | #13; +Parser + Ignored blank; + p = t*; + t = identifier | if; diff --git a/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.input b/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.input new file mode 100644 index 0000000..067f188 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.input @@ -0,0 +1,4 @@ +z10 +00ff1 +fff +00fg1 diff --git a/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.sablecc b/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.sablecc new file mode 100644 index 0000000..01a8619 --- /dev/null +++ b/contrib/nitcc/t/inf5000-04-lexer-priorite_declaree.sablecc @@ -0,0 +1,11 @@ +Grammar priorite_declaree; +Lexer + letter = 'a'..'z'; + digit = '0'..'9'; + identifier = letter(letter|digit)*; + hexinteger = (digit|'a'..'f')+ Except identifier; + blank = ' ' | #9 | #10 | #13; +Parser + Ignored blank; + p = t*; + t = identifier | hexinteger; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.input b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.input new file mode 100644 index 0000000..2ab63cf --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.input @@ -0,0 +1,5 @@ +5 + 4 * 2 +5 - 4 - 2 +5 + 4 + 2 +(5 + 4) * 2 +5 + (4 * 2) diff --git a/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.sablecc new file mode 100644 index 0000000..cf76bd7 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique.sablecc @@ -0,0 +1,18 @@ +Grammar arithmetique; +Lexer +int = ('0'..'9')+; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +exps = exp*; + +exp = {add:} exp '+' exp | + {min:} exp '-' exp | + {mul:} exp '*' exp | + {int:} int | + {par:} '(' exp ')' ; +//alt1 Precedence +//alt1 Left mul; +//alt1 Left add, min; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.input b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.input new file mode 100644 index 0000000..2ab63cf --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.input @@ -0,0 +1,5 @@ +5 + 4 * 2 +5 - 4 - 2 +5 + 4 + 2 +(5 + 4) * 2 +5 + (4 * 2) diff --git a/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.sablecc new file mode 100644 index 0000000..3adf419 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-arithmetique2.sablecc @@ -0,0 +1,17 @@ +Grammar arithmetique; +Lexer +int = ('0'..'9')+; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +exps = exp*; + +exp = {add:} exp '+' factor | + {min:} exp '-' factor | + {factor:} factor ; +factor = {mul:} factor '*' term | + {term:} term ; +term = {int:} int | + {par:} '(' exp ')' ; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-formes.input b/contrib/nitcc/t/inf5000-05-grammaire-formes.input new file mode 100644 index 0000000..6b8c1c1 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-formes.input @@ -0,0 +1 @@ +centre (5pt, 1cm) rayon 10 px diff --git a/contrib/nitcc/t/inf5000-05-grammaire-formes.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-formes.sablecc new file mode 100644 index 0000000..822634f --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-formes.sablecc @@ -0,0 +1,12 @@ +Grammar formes; +Lexer + nombre = ('0'..'9')+; + blank = ' ' | #9 | #10 | #13; + +Parser + Ignored blank; + forme = {cercle:} 'centre' point 'rayon' long | + {segment:} point '--' point ; + point = '(' long ',' long ')' ; + long = nombre unite ; + unite = 'cm' | 'mm' | 'pt' | 'px' ; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-lisp.input b/contrib/nitcc/t/inf5000-05-grammaire-lisp.input new file mode 100644 index 0000000..5ac2401 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-lisp.input @@ -0,0 +1 @@ +(ida(idb idc)(idd ide(idf))()) diff --git a/contrib/nitcc/t/inf5000-05-grammaire-lisp.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-lisp.sablecc new file mode 100644 index 0000000..d752dc9 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-lisp.sablecc @@ -0,0 +1,13 @@ +Grammar lisp; +Lexer +id = ('a'..'z')+; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +item = {par:} '(' list ')' | + {nil:} '(' ')' | + {id:} id ; +list = {many:} item list | + {one:} item ; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-listes.input b/contrib/nitcc/t/inf5000-05-grammaire-listes.input new file mode 100644 index 0000000..188022f --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-listes.input @@ -0,0 +1 @@ +ida idb idc diff --git a/contrib/nitcc/t/inf5000-05-grammaire-listes.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-listes.sablecc new file mode 100644 index 0000000..e8591c7 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-listes.sablecc @@ -0,0 +1,10 @@ +Grammar listes; +Lexer +id = ('a'..'z')+; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +list = {many:} id list | + {one:} id ; diff --git a/contrib/nitcc/t/inf5000-05-grammaire-parentheses.input b/contrib/nitcc/t/inf5000-05-grammaire-parentheses.input new file mode 100644 index 0000000..c9f3fcd --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-parentheses.input @@ -0,0 +1 @@ +((())) diff --git a/contrib/nitcc/t/inf5000-05-grammaire-parentheses.sablecc b/contrib/nitcc/t/inf5000-05-grammaire-parentheses.sablecc new file mode 100644 index 0000000..02b32a6 --- /dev/null +++ b/contrib/nitcc/t/inf5000-05-grammaire-parentheses.sablecc @@ -0,0 +1,9 @@ +Grammar parentheses; +Lexer +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +par = {item:} '(' par ')' | + {empty:} '(' ')' ; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.input b/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.input new file mode 100644 index 0000000..bce0d8f --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.input @@ -0,0 +1 @@ +1+2*(3+4)+5 diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.sablecc b/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.sablecc new file mode 100644 index 0000000..4b3d570 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-calculatrice.sablecc @@ -0,0 +1,15 @@ +Grammar calc; +Lexer + int = ('0'..'9')+; + blank = ' ' | #9 | #10 | #13; + +Parser + Ignored blank; + exprs = expr*; + expr = + {add:} [left:]expr '+' [right:]expr | + {sub:} [left:]expr '-' [right:]expr | + {mul:} [left:]expr '*' [right:]expr | + {int:} int | + {par:} '(' expr ')' ; + Precedence Left mul; Left add, sub; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.input b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.input new file mode 100644 index 0000000..9507760 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.input @@ -0,0 +1,6 @@ +prods = {many:} prods prod | {one:} prod ; +prod = id '=' alts ';' ; +alts = {many:} alts '|' alt | {one:} alt ; +alt = altid atoms | atoms ; +atoms = {many:} atoms atom | {none:} Empty; +atom = {id:} id | {str:} str ; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.sablecc b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.sablecc new file mode 100644 index 0000000..7aa1461 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire.sablecc @@ -0,0 +1,15 @@ +Grammar grammaire; +Lexer +id = ('a'..'z')+; +altid = '{' id ':}'; +str = '\'' (Any* - '\'') '\''; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; +prods = {many:} prods prod | {one:} prod ; +prod = id '=' alts ';' ; +alts = {many:} alts '|' alt | {one:} alt ; +alt = altid atoms | atoms ; +atoms = {many:} atoms atom | {none:} ; +atom = {id:} id | {str:} str ; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.input b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.input new file mode 100644 index 0000000..9507760 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.input @@ -0,0 +1,6 @@ +prods = {many:} prods prod | {one:} prod ; +prod = id '=' alts ';' ; +alts = {many:} alts '|' alt | {one:} alt ; +alt = altid atoms | atoms ; +atoms = {many:} atoms atom | {none:} Empty; +atom = {id:} id | {str:} str ; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.sablecc b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.sablecc new file mode 100644 index 0000000..0f99f0c --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-grammaire2.sablecc @@ -0,0 +1,13 @@ +Grammar grammaire; +Lexer +id = ('a'..'z')+; +altid = '{' id ':}'; +str = '\'' (Any* - '\'') '\''; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; +prods = prod+; +prod = id '=' (alt Separator '|')+ ';' ; +alt = altid? atom* ; +atom = {id:} id | {str:} str ; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-instructions.input b/contrib/nitcc/t/inf5000-06-grammaire2-instructions.input new file mode 100644 index 0000000..5e77413 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-instructions.input @@ -0,0 +1,2 @@ +x = y; +while (z) { print(t); k=u; } diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-instructions.sablecc b/contrib/nitcc/t/inf5000-06-grammaire2-instructions.sablecc new file mode 100644 index 0000000..c0cb7f7 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-instructions.sablecc @@ -0,0 +1,22 @@ +Grammar instuctions; +Lexer +id = ('a'..'z')+; +blank = ' ' | #9 | #10 | #13; + +Parser +Ignored blank; + +prog = stmt* ; +stmt = + {assign:} id '=' expr ';' | + {print:} 'print' '(' expr ')' ';' | + {while:} 'while' '(' expr ')' '{' stmt* '}' +//alt1 | {until:} 'do' '{' stmt* '}' 'until' '(' expr ')' ';' +//alt2 | {if:} 'if' '('expr')' '{'stmt*'}' elsex? +//alt3 | {call:} id '(' args ')' ';' + ; + +//alt2 elsex = 'else' '{' stmt* '}' ; +//alt3 args = (expr Separator ',')* ; + +expr = id; diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-polygone.input b/contrib/nitcc/t/inf5000-06-grammaire2-polygone.input new file mode 100644 index 0000000..23aa920 --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-polygone.input @@ -0,0 +1 @@ +((0x,0y), (10, 0deg), (0x, 10y)) diff --git a/contrib/nitcc/t/inf5000-06-grammaire2-polygone.sablecc b/contrib/nitcc/t/inf5000-06-grammaire2-polygone.sablecc new file mode 100644 index 0000000..41b031b --- /dev/null +++ b/contrib/nitcc/t/inf5000-06-grammaire2-polygone.sablecc @@ -0,0 +1,11 @@ +Grammar polygones; +Lexer + num = ('0'..'9')+; + blank = ' ' | #9 | #10 | #13; + +Parser + Ignored blank; + polygone = '(' (point Separator ',')* ')' ; + point = + {cart:} '(' num 'x' ',' num 'y' ')' | + {pol:} '(' num ',' num 'deg' ')' ; diff --git a/contrib/nitcc/t/lalr.sablecc b/contrib/nitcc/t/lalr.sablecc new file mode 100644 index 0000000..a29e7ee --- /dev/null +++ b/contrib/nitcc/t/lalr.sablecc @@ -0,0 +1,5 @@ +Grammar lalr; +Parser +p = q 'a' | r 'b' ; +q = 'x' ; +r = 'x'; diff --git a/contrib/nitcc/t/lexer-c-comment.sablecc b/contrib/nitcc/t/lexer-c-comment.sablecc new file mode 100644 index 0000000..c4f494a --- /dev/null +++ b/contrib/nitcc/t/lexer-c-comment.sablecc @@ -0,0 +1,19 @@ +Grammar re; +Lexer + + notst = Any - '*'; + notstsl = notst - '/'; + + com1 = '/*' (notst | '*'+ notstsl)* '*'+ '/'; + com2 = '/*' notst* ('*' (notstsl notst*)?)* '*/'; //alt1 //alt2 //alt3 //alt4 + //alt1 com2 = Shortest ('/*' Any* '*/'); + //alt2 com2 = '/*' (Any* - '*/') '*/'; + //alt3 com2 = '/*' (('' Lookahead Not '*/') Any)* '*/'; + //alt4 com2 = '/*' (Any* Except (Any* '*/' Any*)) '*/'; + + dummy = notst | notstsl; + +Parser + +p = com1 | com2 | dummy; + diff --git a/contrib/nitcc/t/lexer-errors.sablecc b/contrib/nitcc/t/lexer-errors.sablecc new file mode 100644 index 0000000..dd7290c --- /dev/null +++ b/contrib/nitcc/t/lexer-errors.sablecc @@ -0,0 +1,15 @@ +Grammar re; +Lexer + + //alt1 a = ''; + //alt2 a = 'a' - 'a'; + //alt3 a = a; + //alt4 a = b; b = a; + //alt5 a = fail; + //alt6 a = 'a'; i = 'i'; + //alt7 a = '' Lookahead 'a'; + //alt8 a = 'a'; + +Parser +//alt8 Ignored fail; +t = a; diff --git a/contrib/nitcc/t/lexer-implicit-longest-and-priority.input b/contrib/nitcc/t/lexer-implicit-longest-and-priority.input new file mode 100644 index 0000000..bf59612 --- /dev/null +++ b/contrib/nitcc/t/lexer-implicit-longest-and-priority.input @@ -0,0 +1 @@ +aabb diff --git a/contrib/nitcc/t/lexer-implicit-longest-and-priority.sablecc b/contrib/nitcc/t/lexer-implicit-longest-and-priority.sablecc new file mode 100644 index 0000000..07ad6ef --- /dev/null +++ b/contrib/nitcc/t/lexer-implicit-longest-and-priority.sablecc @@ -0,0 +1,10 @@ +Grammar re; +Lexer +a='a'; +anb='a' Lookahead Not 'b'; +ab='ab'; //alt1 ab='DUMMY'; +b='b'; +blank=#10|#13|#32; +Parser +Ignored blank; +t = a | anb | ab | b; diff --git a/contrib/nitcc/t/lexer-implicit-longest.input b/contrib/nitcc/t/lexer-implicit-longest.input new file mode 100644 index 0000000..e170dc3 --- /dev/null +++ b/contrib/nitcc/t/lexer-implicit-longest.input @@ -0,0 +1 @@ +ababac diff --git a/contrib/nitcc/t/lexer-implicit-longest.sablecc b/contrib/nitcc/t/lexer-implicit-longest.sablecc new file mode 100644 index 0000000..af88c9a --- /dev/null +++ b/contrib/nitcc/t/lexer-implicit-longest.sablecc @@ -0,0 +1,8 @@ +Grammar re; +Lexer +a = 'a' Lookahead 'b'; //alt1 a = 'a' Lookahead ('b'|'c'); +b = 'ab'; +blank = #10 | #13 | #32; +Parser +Ignored blank; +t = a | b; diff --git a/contrib/nitcc/t/lexer-markers.input b/contrib/nitcc/t/lexer-markers.input new file mode 100644 index 0000000..5a69e17 --- /dev/null +++ b/contrib/nitcc/t/lexer-markers.input @@ -0,0 +1 @@ +aabacaba diff --git a/contrib/nitcc/t/lexer-markers.sablecc b/contrib/nitcc/t/lexer-markers.sablecc new file mode 100644 index 0000000..24393c5 --- /dev/null +++ b/contrib/nitcc/t/lexer-markers.sablecc @@ -0,0 +1,10 @@ +Grammar re; +Lexer +a = 'a'; +b = 'a' 'b' 'a' 'c'; //alt1 //alt2 +//alt1 b = 'a' 'b' 'a'* 'c'; +//alt2 b = 'a'* 'b' 'a' 'c'; +blank = #10 | #13 | #32; +Parser +Ignored blank; +t = a | b; diff --git a/contrib/nitcc/t/lexer-precedences.input b/contrib/nitcc/t/lexer-precedences.input new file mode 100644 index 0000000..b34225a --- /dev/null +++ b/contrib/nitcc/t/lexer-precedences.input @@ -0,0 +1 @@ +aababa diff --git a/contrib/nitcc/t/lexer-precedences.sablecc b/contrib/nitcc/t/lexer-precedences.sablecc new file mode 100644 index 0000000..9401c25 --- /dev/null +++ b/contrib/nitcc/t/lexer-precedences.sablecc @@ -0,0 +1,14 @@ +Grammar re; +Lexer + //alt1,2,3 a = 'a'; b = 'a' | 'b' ; + //alt4,5 a = 'a' | 'c' ; b = 'a' | 'b' ; + //alt6,7 a = 'a' ; b = 'b' ; + //alt8 a = ('a' Lookahead 'b') | 'c'; b = 'a'; + //alt9,10 a = 'a'; b = 'b'; + +xa = a; xb =b; //alt2,5,7,10 xa = a ; xb = b - a; //Precedence a > b; //alt3 xa = a - b ; xb = b; //Precedence b > a; +blank = #10 | #13; + +Parser +Ignored blank; +t = xa | xb; diff --git a/contrib/nitcc/t/lexer-shortest-longest.input b/contrib/nitcc/t/lexer-shortest-longest.input new file mode 100644 index 0000000..a9af52d --- /dev/null +++ b/contrib/nitcc/t/lexer-shortest-longest.input @@ -0,0 +1 @@ +abaaba diff --git a/contrib/nitcc/t/lexer-shortest-longest.sablecc b/contrib/nitcc/t/lexer-shortest-longest.sablecc new file mode 100644 index 0000000..c449061 --- /dev/null +++ b/contrib/nitcc/t/lexer-shortest-longest.sablecc @@ -0,0 +1,20 @@ +Grammar re; +Lexer + a = 'a'; + ab = 'ab'; + a_ab = a | ab; + alb_ab = 'a' Lookahead Not 'b' | 'ab'; + s = Shortest(a_ab); + l = Longest(a_ab); + dummy = 'x' (a|ab|alb_ab|s|l); + blank = #10 | #13 | #32; + +Parser +Ignored blank; + t = + ab | l | //alt1 +//alt1 a | s | +//alt2 a | +//alt3 alb_ab | + dummy; + diff --git a/contrib/nitcc/t/lexer-shortest-longest2.input b/contrib/nitcc/t/lexer-shortest-longest2.input new file mode 100644 index 0000000..6f27bcf --- /dev/null +++ b/contrib/nitcc/t/lexer-shortest-longest2.input @@ -0,0 +1 @@ +aab diff --git a/contrib/nitcc/t/lexer-shortest-longest2.sablecc b/contrib/nitcc/t/lexer-shortest-longest2.sablecc new file mode 100644 index 0000000..45cff19 --- /dev/null +++ b/contrib/nitcc/t/lexer-shortest-longest2.sablecc @@ -0,0 +1,12 @@ +Grammar re; +Lexer +a = 'a' 'b'?; +la = Longest(a); +sa = Shortest(a); +sla = Shortest(la); +dummy = 'X' (a|la|sa|sla); +blank = #10 | #13 | #32; +Parser +Ignored blank; +t = dummy | +a | la; //alt1 a | sa; //alt2 a | sla; //alt3 la | sa; //alt4 la | sla; diff --git a/contrib/nitcc/t/lexer_conflict_token.sablecc b/contrib/nitcc/t/lexer_conflict_token.sablecc new file mode 100644 index 0000000..c4cc6e8 --- /dev/null +++ b/contrib/nitcc/t/lexer_conflict_token.sablecc @@ -0,0 +1,10 @@ +Grammar lexer_conflict_token; + +Lexer + +a = 'a'|'x'; +b = 'b'|'x'; + +Parser + +p = a | b; diff --git a/contrib/nitcc/t/lexer_empty_token.sablecc b/contrib/nitcc/t/lexer_empty_token.sablecc new file mode 100644 index 0000000..f053667 --- /dev/null +++ b/contrib/nitcc/t/lexer_empty_token.sablecc @@ -0,0 +1,10 @@ +Grammar lexer_empty_token; + +Lexer + +a= 'a'*; +b= ''; + +Parser + +p = a | b; diff --git a/contrib/nitcc/t/lexer_features.input b/contrib/nitcc/t/lexer_features.input new file mode 100644 index 0000000..8a72a2e --- /dev/null +++ b/contrib/nitcc/t/lexer_features.input @@ -0,0 +1,5 @@ +i if iff ifff +70 +zero +0xFFff // unseen +192.168.0.1 diff --git a/contrib/nitcc/t/lexer_features.input2 b/contrib/nitcc/t/lexer_features.input2 new file mode 100644 index 0000000..9a62de2 --- /dev/null +++ b/contrib/nitcc/t/lexer_features.input2 @@ -0,0 +1 @@ +10.5 diff --git a/contrib/nitcc/t/lr1.sablecc b/contrib/nitcc/t/lr1.sablecc new file mode 100644 index 0000000..a995b61 --- /dev/null +++ b/contrib/nitcc/t/lr1.sablecc @@ -0,0 +1,5 @@ +Grammar lr1; +Parser +p = q 'a' q 'b' | r 'a'; +q = 'x'; +r = 'x'; diff --git a/contrib/nitcc/t/modif.input1 b/contrib/nitcc/t/modif.input1 new file mode 100644 index 0000000..7ec9a4b --- /dev/null +++ b/contrib/nitcc/t/modif.input1 @@ -0,0 +1 @@ +aa \ No newline at end of file diff --git a/contrib/nitcc/t/modif.input2 b/contrib/nitcc/t/modif.input2 new file mode 100644 index 0000000..4063933 --- /dev/null +++ b/contrib/nitcc/t/modif.input2 @@ -0,0 +1 @@ +abccbbcccdcba \ No newline at end of file diff --git a/contrib/nitcc/t/modif.input3 b/contrib/nitcc/t/modif.input3 new file mode 100644 index 0000000..28db331 --- /dev/null +++ b/contrib/nitcc/t/modif.input3 @@ -0,0 +1 @@ +abba \ No newline at end of file diff --git a/contrib/nitcc/t/modif.input4 b/contrib/nitcc/t/modif.input4 new file mode 100644 index 0000000..2827b0f --- /dev/null +++ b/contrib/nitcc/t/modif.input4 @@ -0,0 +1 @@ +abcddcba \ No newline at end of file diff --git a/contrib/nitcc/t/modif.sablecc b/contrib/nitcc/t/modif.sablecc new file mode 100644 index 0000000..47ef2b6 --- /dev/null +++ b/contrib/nitcc/t/modif.sablecc @@ -0,0 +1,8 @@ +Grammar modif; + +Parser + +p = 'a' q* 'a'; +q = 'b' r+ 'b'; +r = 'c' s? 'c'; +s = 'd'; diff --git a/contrib/nitcc/t/nit_expr.sablecc b/contrib/nitcc/t/nit_expr.sablecc new file mode 100644 index 0000000..18d88fc --- /dev/null +++ b/contrib/nitcc/t/nit_expr.sablecc @@ -0,0 +1,11 @@ +Grammar nit_expr; +Parser +e = + e '[' e ']' | + '[' e ']' | + '[' e '..' e '[' | + '[' e '..' e ']' | + 'id' e | + 'id'; + + diff --git a/contrib/nitcc/t/not_lalr.sablecc b/contrib/nitcc/t/not_lalr.sablecc new file mode 100644 index 0000000..7d4ca5d --- /dev/null +++ b/contrib/nitcc/t/not_lalr.sablecc @@ -0,0 +1,5 @@ +Grammar not_lalr; +Parser +p = 'a' x 'a' | 'a' y 'b' | 'b' y 'a' | 'b' x 'b' ; +x = 'a'; +y = 'a'; diff --git a/contrib/nitcc/t/not_slr.sablecc b/contrib/nitcc/t/not_slr.sablecc new file mode 100644 index 0000000..3096599 --- /dev/null +++ b/contrib/nitcc/t/not_slr.sablecc @@ -0,0 +1,7 @@ +Grammar not_slr; + +Parser + +s = g '=' d | d ; +g = '*' d | 'id' ; +d = g ; diff --git a/contrib/nitcc/t/pri.sablecc b/contrib/nitcc/t/pri.sablecc new file mode 100644 index 0000000..1106403 --- /dev/null +++ b/contrib/nitcc/t/pri.sablecc @@ -0,0 +1,7 @@ +Grammar pri; +Parser +a = 'p' p | 'q' q | 'r' r? ; +p = p '+' p | 'p'; +q = q q | 'q' ; +r = r2?; +r2 = 'r'; diff --git a/contrib/nitcc/t/priority.sablecc b/contrib/nitcc/t/priority.sablecc new file mode 100644 index 0000000..1fe549e --- /dev/null +++ b/contrib/nitcc/t/priority.sablecc @@ -0,0 +1,7 @@ +Grammar priority; +Parser +e = + e '+' e | + e '-' e | + e '*' e | + '0' ; diff --git a/contrib/nitcc/t/qualified.sablecc b/contrib/nitcc/t/qualified.sablecc new file mode 100644 index 0000000..d3a13ed --- /dev/null +++ b/contrib/nitcc/t/qualified.sablecc @@ -0,0 +1,8 @@ +Grammar qualified; + +Parser + e = r q id; + r = e '.' | ; + q = qe+ | ; + qe = id '::' ; + id = 'id'; diff --git a/contrib/nitcc/t/run b/contrib/nitcc/t/run new file mode 100755 index 0000000..fbc7e8c --- /dev/null +++ b/contrib/nitcc/t/run @@ -0,0 +1 @@ +./t "$@" *.sablecc ../examples/*.sablecc diff --git a/contrib/nitcc/t/sav/calc.res b/contrib/nitcc/t/sav/calc.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/empty.alt1.res b/contrib/nitcc/t/sav/empty.alt1.res new file mode 100644 index 0000000..7d3ae78 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt1.res @@ -0,0 +1,2 @@ +* parse error in state Start on token Eof@(16:1-16:1)='' +NParserError@(16:1-16:1)='' diff --git a/contrib/nitcc/t/sav/empty.alt2.res b/contrib/nitcc/t/sav/empty.alt2.res new file mode 100644 index 0000000..983984c --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt2.res @@ -0,0 +1 @@ +Error: grammar with no production diff --git a/contrib/nitcc/t/sav/empty.alt3.input.res b/contrib/nitcc/t/sav/empty.alt3.input.res new file mode 100644 index 0000000..821fc27 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt3.input.res @@ -0,0 +1 @@ +1,1. Syntax error: Unexpected character 'a'. diff --git a/contrib/nitcc/t/sav/empty.alt3.input2.res b/contrib/nitcc/t/sav/empty.alt3.input2.res new file mode 100644 index 0000000..d67f8e9 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt3.input2.res @@ -0,0 +1 @@ +TEnd@1,1: diff --git a/contrib/nitcc/t/sav/empty.alt3.res b/contrib/nitcc/t/sav/empty.alt3.res new file mode 100644 index 0000000..983984c --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt3.res @@ -0,0 +1 @@ +Error: grammar with no production diff --git a/contrib/nitcc/t/sav/empty.alt4.res b/contrib/nitcc/t/sav/empty.alt4.res new file mode 100644 index 0000000..983984c --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt4.res @@ -0,0 +1 @@ +Error: grammar with no production diff --git a/contrib/nitcc/t/sav/empty.alt5.input.res b/contrib/nitcc/t/sav/empty.alt5.input.res new file mode 100644 index 0000000..8088cc2 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt5.input.res @@ -0,0 +1,2 @@ +T_A@1,1:a +TEnd@1,2: diff --git a/contrib/nitcc/t/sav/empty.alt5.input2.res b/contrib/nitcc/t/sav/empty.alt5.input2.res new file mode 100644 index 0000000..d67f8e9 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt5.input2.res @@ -0,0 +1 @@ +TEnd@1,1: diff --git a/contrib/nitcc/t/sav/empty.alt5.res b/contrib/nitcc/t/sav/empty.alt5.res new file mode 100644 index 0000000..983984c --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt5.res @@ -0,0 +1 @@ +Error: grammar with no production diff --git a/contrib/nitcc/t/sav/empty.alt6.input.res b/contrib/nitcc/t/sav/empty.alt6.input.res new file mode 100644 index 0000000..8088cc2 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt6.input.res @@ -0,0 +1,2 @@ +T_A@1,1:a +TEnd@1,2: diff --git a/contrib/nitcc/t/sav/empty.alt6.input2.res b/contrib/nitcc/t/sav/empty.alt6.input2.res new file mode 100644 index 0000000..d67f8e9 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt6.input2.res @@ -0,0 +1 @@ +TEnd@1,1: diff --git a/contrib/nitcc/t/sav/empty.alt6.res b/contrib/nitcc/t/sav/empty.alt6.res new file mode 100644 index 0000000..983984c --- /dev/null +++ b/contrib/nitcc/t/sav/empty.alt6.res @@ -0,0 +1 @@ +Error: grammar with no production diff --git a/contrib/nitcc/t/sav/empty.input.res b/contrib/nitcc/t/sav/empty.input.res new file mode 100644 index 0000000..02b99f2 --- /dev/null +++ b/contrib/nitcc/t/sav/empty.input.res @@ -0,0 +1,2 @@ +NParserError@(1:2-1:2)='' +Nodes diff --git a/contrib/nitcc/t/sav/empty.input2.res b/contrib/nitcc/t/sav/empty.input2.res new file mode 100644 index 0000000..f22973a --- /dev/null +++ b/contrib/nitcc/t/sav/empty.input2.res @@ -0,0 +1,2 @@ +NLexerError@(1:1-1:1)='' +Nodes diff --git a/contrib/nitcc/t/sav/empty.res b/contrib/nitcc/t/sav/empty.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/expression.res b/contrib/nitcc/t/sav/expression.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/if.res b/contrib/nitcc/t/sav/if.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-automate.input.res b/contrib/nitcc/t/sav/inf5000-04-lexer-automate.input.res new file mode 100644 index 0000000..11142bd --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-automate.input.res @@ -0,0 +1,46 @@ +Start + p + Nodes + t_1 + if@(1:1-1:3)='if' + t_0 + id@(1:4-1:7)='iff' + t_0 + id@(1:8-1:11)='iff' + t_0 + id@(1:12-1:13)='i' + t_0 + id@(1:14-1:15)='f' + t_0 + id@(2:1-2:6)='if50i' + t_1 + if@(3:1-3:3)='if' + t_2 + int@(3:4-3:6)='50' + t_0 + id@(3:7-3:8)='i' + t_2 + int@(4:1-4:3)='50' + t_3 + float@(5:1-5:6)='50.50' + t_2 + int@(6:1-6:3)='50' + t_4 + dot@(6:3-6:4)='.' + t_4 + dot@(7:1-7:2)='.' + t_2 + int@(7:2-7:4)='50' + t_2 + int@(8:1-8:3)='50' + t_4 + dot@(8:3-8:4)='.' + t_0 + id@(8:4-8:5)='f' + t_0 + id@(9:1-9:2)='f' + t_4 + dot@(9:2-9:3)='.' + t_2 + int@(9:3-9:5)='50' + Eof@(10:1-10:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-automate.res b/contrib/nitcc/t/sav/inf5000-04-lexer-automate.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input.res b/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input.res new file mode 100644 index 0000000..84152ca --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input.res @@ -0,0 +1,22 @@ +Start + p + Nodes + t_2 + if@(1:1-1:3)='if' + t_0 + identifier@(1:4-1:7)='iff' + t_0 + identifier@(1:8-1:11)='iff' + t_0 + identifier@(1:12-1:13)='i' + t_0 + identifier@(1:14-1:15)='f' + t_0 + identifier@(2:1-2:6)='if50i' + t_2 + if@(3:1-3:3)='if' + t_1 + comma@(3:3-3:4)=',' + t_0 + identifier@(3:4-3:5)='i' + Eof@(4:1-4:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input2.res b/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input2.res new file mode 100644 index 0000000..eaa2468 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-demo.input2.res @@ -0,0 +1,3 @@ +NLexerError@(1:1-1:1)='5' +Nodes + p diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-demo.res b/contrib/nitcc/t/sav/inf5000-04-lexer-demo.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input.res b/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input.res new file mode 100644 index 0000000..63d3f49 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input.res @@ -0,0 +1,6 @@ +Start + p + Nodes + t_1 + b@(1:1-1:34)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab' + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input2.res b/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input2.res new file mode 100644 index 0000000..29e09b2 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.input2.res @@ -0,0 +1,68 @@ +Start + p + Nodes + t_0 + a@(1:1-1:2)='a' + t_0 + a@(1:2-1:3)='a' + t_0 + a@(1:3-1:4)='a' + t_0 + a@(1:4-1:5)='a' + t_0 + a@(1:5-1:6)='a' + t_0 + a@(1:6-1:7)='a' + t_0 + a@(1:7-1:8)='a' + t_0 + a@(1:8-1:9)='a' + t_0 + a@(1:9-1:10)='a' + t_0 + a@(1:10-1:11)='a' + t_0 + a@(1:11-1:12)='a' + t_0 + a@(1:12-1:13)='a' + t_0 + a@(1:13-1:14)='a' + t_0 + a@(1:14-1:15)='a' + t_0 + a@(1:15-1:16)='a' + t_0 + a@(1:16-1:17)='a' + t_0 + a@(1:17-1:18)='a' + t_0 + a@(1:18-1:19)='a' + t_0 + a@(1:19-1:20)='a' + t_0 + a@(1:20-1:21)='a' + t_0 + a@(1:21-1:22)='a' + t_0 + a@(1:22-1:23)='a' + t_0 + a@(1:23-1:24)='a' + t_0 + a@(1:24-1:25)='a' + t_0 + a@(1:25-1:26)='a' + t_0 + a@(1:26-1:27)='a' + t_0 + a@(1:27-1:28)='a' + t_0 + a@(1:28-1:29)='a' + t_0 + a@(1:29-1:30)='a' + t_0 + a@(1:30-1:31)='a' + t_0 + a@(1:31-1:32)='a' + t_0 + a@(1:32-1:33)='a' + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.res b/contrib/nitcc/t/sav/inf5000-04-lexer-pire_cout.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.input.res b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.input.res new file mode 100644 index 0000000..e5baa77 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.input.res @@ -0,0 +1,12 @@ +Start + p + Nodes + t_0 + identifier@(1:1-1:2)='i' + t_0 + identifier@(1:3-1:4)='f' + t_1 + if@(2:1-2:3)='if' + t_0 + identifier@(3:1-3:4)='ify' + Eof@(4:1-4:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.res b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_d_inclusion.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.input.res b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.input.res new file mode 100644 index 0000000..057c58a --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.input.res @@ -0,0 +1,6 @@ +T_Identifier@1,1:z10 +T_Hexinteger@2,1:00ff1 +T_Identifier@3,1:fff +T_Hexinteger@4,1:00f +T_Identifier@4,4:g1 +TEnd@5,1: diff --git a/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.res b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.res new file mode 100644 index 0000000..284eee7 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-04-lexer-priorite_declaree.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(6:34-6:34)='E' +NLexerError@(6:34-6:34)='E' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.alt1.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.alt1.res new file mode 100644 index 0000000..bb9f116 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.alt1.res @@ -0,0 +1,2 @@ +* parse error in state grammar on token NLexerError@(16:1-16:2)='Pr' +NLexerError@(16:1-16:2)='Pr' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.input.res new file mode 100644 index 0000000..974aa14 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.input.res @@ -0,0 +1,60 @@ +Start + exps + Nodes + exp_add + exp_int + int@(1:1-1:2)='5' + '+'@(1:3-1:4) + exp_mul + exp_int + int@(1:5-1:6)='4' + '*'@(1:7-1:8) + exp_int + int@(1:9-1:10)='2' + exp_min + exp_int + int@(2:1-2:2)='5' + '-'@(2:3-2:4) + exp_min + exp_int + int@(2:5-2:6)='4' + '-'@(2:7-2:8) + exp_int + int@(2:9-2:10)='2' + exp_add + exp_int + int@(3:1-3:2)='5' + '+'@(3:3-3:4) + exp_add + exp_int + int@(3:5-3:6)='4' + '+'@(3:7-3:8) + exp_int + int@(3:9-3:10)='2' + exp_mul + exp_par + '('@(4:1-4:2) + exp_add + exp_int + int@(4:2-4:3)='5' + '+'@(4:4-4:5) + exp_int + int@(4:6-4:7)='4' + ')'@(4:7-4:8) + '*'@(4:9-4:10) + exp_int + int@(4:11-4:12)='2' + exp_add + exp_int + int@(5:1-5:2)='5' + '+'@(5:3-5:4) + exp_par + '('@(5:5-5:6) + exp_mul + exp_int + int@(5:6-5:7)='4' + '*'@(5:8-5:9) + exp_int + int@(5:10-5:11)='2' + ')'@(5:11-5:12) + Eof@(6:1-6:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.input.res new file mode 100644 index 0000000..0f4c052 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.input.res @@ -0,0 +1,81 @@ +Start + exps + Nodes + exp_add + exp_factor + factor_term + term_int + int@(1:1-1:2)='5' + '+'@(1:3-1:4) + factor_mul + factor_term + term_int + int@(1:5-1:6)='4' + '*'@(1:7-1:8) + term_int + int@(1:9-1:10)='2' + exp_min + exp_min + exp_factor + factor_term + term_int + int@(2:1-2:2)='5' + '-'@(2:3-2:4) + factor_term + term_int + int@(2:5-2:6)='4' + '-'@(2:7-2:8) + factor_term + term_int + int@(2:9-2:10)='2' + exp_add + exp_add + exp_factor + factor_term + term_int + int@(3:1-3:2)='5' + '+'@(3:3-3:4) + factor_term + term_int + int@(3:5-3:6)='4' + '+'@(3:7-3:8) + factor_term + term_int + int@(3:9-3:10)='2' + exp_factor + factor_mul + factor_term + term_par + '('@(4:1-4:2) + exp_add + exp_factor + factor_term + term_int + int@(4:2-4:3)='5' + '+'@(4:4-4:5) + factor_term + term_int + int@(4:6-4:7)='4' + ')'@(4:7-4:8) + '*'@(4:9-4:10) + term_int + int@(4:11-4:12)='2' + exp_add + exp_factor + factor_term + term_int + int@(5:1-5:2)='5' + '+'@(5:3-5:4) + factor_term + term_par + '('@(5:5-5:6) + exp_factor + factor_mul + factor_term + term_int + int@(5:6-5:7)='4' + '*'@(5:8-5:9) + term_int + int@(5:10-5:11)='2' + ')'@(5:11-5:12) + Eof@(6:1-6:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-arithmetique2.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-formes.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-formes.input.res new file mode 100644 index 0000000..f603e3b --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-formes.input.res @@ -0,0 +1,21 @@ +Start + forme_cercle + 'centre'@(1:1-1:7) + point + '('@(1:8-1:9) + long + nombre@(1:9-1:10)='5' + unite_2 + 'pt'@(1:10-1:12) + ','@(1:12-1:13) + long + nombre@(1:14-1:15)='1' + unite_0 + 'cm'@(1:15-1:17) + ')'@(1:17-1:18) + 'rayon'@(1:19-1:24) + long + nombre@(1:25-1:27)='10' + unite_3 + 'px'@(1:28-1:30) + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-formes.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-formes.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.input.res new file mode 100644 index 0000000..1904ff6 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.input.res @@ -0,0 +1,39 @@ +Start + item_par + '('@(1:1-1:2) + list_many + item_id + id@(1:2-1:5)='ida' + list_many + item_par + '('@(1:5-1:6) + list_many + item_id + id@(1:6-1:9)='idb' + list_one + item_id + id@(1:10-1:13)='idc' + ')'@(1:13-1:14) + list_many + item_par + '('@(1:14-1:15) + list_many + item_id + id@(1:15-1:18)='idd' + list_many + item_id + id@(1:19-1:22)='ide' + list_one + item_par + '('@(1:22-1:23) + list_one + item_id + id@(1:23-1:26)='idf' + ')'@(1:26-1:27) + ')'@(1:27-1:28) + list_one + item_nil + '('@(1:28-1:29) + ')'@(1:29-1:30) + ')'@(1:30-1:31) + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-lisp.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-listes.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-listes.input.res new file mode 100644 index 0000000..d658dae --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-listes.input.res @@ -0,0 +1,8 @@ +Start + list_many + id@(1:1-1:4)='ida' + list_many + id@(1:5-1:8)='idb' + list_one + id@(1:9-1:12)='idc' + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-listes.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-listes.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.input.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.input.res new file mode 100644 index 0000000..65c805b --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.input.res @@ -0,0 +1,11 @@ +Start + par_item + '('@(1:1-1:2) + par_item + '('@(1:2-1:3) + par_empty + '('@(1:3-1:4) + ')'@(1:4-1:5) + ')'@(1:5-1:6) + ')'@(1:6-1:7) + Eof@(2:1-2:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.res b/contrib/nitcc/t/sav/inf5000-05-grammaire-parentheses.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.input.res new file mode 100644 index 0000000..2b41938 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.input.res @@ -0,0 +1,12 @@ +T_Int@1,1:1 +TAnonymous@1,2:+ +T_Int@1,3:2 +TAnonymous@1,4:* +TAnonymous@1,5:( +T_Int@1,6:3 +TAnonymous@1,7:+ +T_Int@1,8:4 +TAnonymous@1,9:) +TAnonymous@1,10:+ +T_Int@1,11:5 +TEnd@2,1: diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.res new file mode 100644 index 0000000..afd46a2 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-calculatrice.res @@ -0,0 +1,2 @@ +* parse error in state grammar on token NLexerError@(15:7-15:8)='Pr' +NLexerError@(15:7-15:8)='Pr' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.input.res new file mode 100644 index 0000000..1bddbfc --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.input.res @@ -0,0 +1,109 @@ +NLexerError@(5:38-5:38)='E' +Nodes + prods_many + prods_many + prods_many + prods_one + prod + id@(1:1-1:6)='prods' + '='@(1:7-1:8) + alts_many + alts_one + alt_0 + altid@(1:9-1:16)='{many:}' + atoms_many + atoms_many + atoms_none + atom_id + id@(1:17-1:22)='prods' + atom_id + id@(1:23-1:27)='prod' + '|'@(1:29-1:30) + alt_0 + altid@(1:31-1:37)='{one:}' + atoms_many + atoms_none + atom_id + id@(1:38-1:42)='prod' + ';'@(1:43-1:44) + prod + id@(2:1-2:5)='prod' + '='@(2:6-2:7) + alts_one + alt_1 + atoms_many + atoms_many + atoms_many + atoms_many + atoms_none + atom_id + id@(2:8-2:10)='id' + atom_str + str@(2:11-2:14)='\'=\'' + atom_id + id@(2:15-2:19)='alts' + atom_str + str@(2:20-2:23)='\';\'' + ';'@(2:24-2:25) + prod + id@(3:1-3:5)='alts' + '='@(3:6-3:7) + alts_many + alts_one + alt_0 + altid@(3:8-3:15)='{many:}' + atoms_many + atoms_many + atoms_many + atoms_none + atom_id + id@(3:16-3:20)='alts' + atom_str + str@(3:21-3:24)='\'|\'' + atom_id + id@(3:25-3:28)='alt' + '|'@(3:29-3:30) + alt_0 + altid@(3:31-3:37)='{one:}' + atoms_many + atoms_none + atom_id + id@(3:38-3:41)='alt' + ';'@(3:42-3:43) + prod + id@(4:1-4:4)='alt' + '='@(4:5-4:6) + alts_many + alts_one + alt_1 + atoms_many + atoms_many + atoms_none + atom_id + id@(4:7-4:12)='altid' + atom_id + id@(4:13-4:18)='atoms' + '|'@(4:19-4:20) + alt_1 + atoms_many + atoms_none + atom_id + id@(4:21-4:26)='atoms' + ';'@(4:27-4:28) + id@(5:1-5:6)='atoms' + '='@(5:7-5:8) + alts_many + alts_one + alt_0 + altid@(5:9-5:16)='{many:}' + atoms_many + atoms_many + atoms_none + atom_id + id@(5:17-5:22)='atoms' + atom_id + id@(5:23-5:27)='atom' + '|'@(5:28-5:29) + alt_0 + altid@(5:30-5:37)='{none:}' + atoms_none diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.input.res new file mode 100644 index 0000000..78e60f9 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.input.res @@ -0,0 +1,41 @@ +T_Id@1,1:prods +TAnonymous@1,7:= +T_Altid@1,9:{many:} +T_Id@1,17:prods +T_Id@1,23:prod +TAnonymous@1,29:| +T_Altid@1,31:{one:} +T_Id@1,38:prod +TAnonymous@1,43:; +T_Id@2,1:prod +TAnonymous@2,6:= +T_Id@2,8:id +T_Str@2,11:'=' +T_Id@2,15:alts +T_Str@2,20:';' +TAnonymous@2,24:; +T_Id@3,1:alts +TAnonymous@3,6:= +T_Altid@3,8:{many:} +T_Id@3,16:alts +T_Str@3,21:'|' +T_Id@3,25:alt +TAnonymous@3,29:| +T_Altid@3,31:{one:} +T_Id@3,38:alt +TAnonymous@3,42:; +T_Id@4,1:alt +TAnonymous@4,5:= +T_Id@4,7:altid +T_Id@4,13:atoms +TAnonymous@4,19:| +T_Id@4,21:atoms +TAnonymous@4,27:; +T_Id@5,1:atoms +TAnonymous@5,7:= +T_Altid@5,9:{many:} +T_Id@5,17:atoms +T_Id@5,23:atom +TAnonymous@5,28:| +T_Altid@5,30:{none:} +5,38. Syntax error: Unexpected character 'E'. diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.res new file mode 100644 index 0000000..c227e39 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-grammaire2.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Parser' id '=' alts on token '('@(11:15-11:16) +NParserError@(11:15-11:16)='(' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.input.res new file mode 100644 index 0000000..40503ba --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.input.res @@ -0,0 +1,32 @@ +Start + prog + Nodes + stmt_assign + id@(1:1-1:2)='x' + '='@(1:3-1:4) + expr + id@(1:5-1:6)='y' + ';'@(1:6-1:7) + stmt_while + 'while'@(2:1-2:6) + '('@(2:7-2:8) + expr + id@(2:8-2:9)='z' + ')'@(2:9-2:10) + '{'@(2:11-2:12) + Nodes + stmt_print + 'print'@(2:13-2:18) + '('@(2:18-2:19) + expr + id@(2:19-2:20)='t' + ')'@(2:20-2:21) + ';'@(2:21-2:22) + stmt_assign + id@(2:23-2:24)='k' + '='@(2:24-2:25) + expr + id@(2:25-2:26)='u' + ';'@(2:26-2:27) + '}'@(2:28-2:29) + Eof@(3:1-3:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt1.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.input.res new file mode 100644 index 0000000..40503ba --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.input.res @@ -0,0 +1,32 @@ +Start + prog + Nodes + stmt_assign + id@(1:1-1:2)='x' + '='@(1:3-1:4) + expr + id@(1:5-1:6)='y' + ';'@(1:6-1:7) + stmt_while + 'while'@(2:1-2:6) + '('@(2:7-2:8) + expr + id@(2:8-2:9)='z' + ')'@(2:9-2:10) + '{'@(2:11-2:12) + Nodes + stmt_print + 'print'@(2:13-2:18) + '('@(2:18-2:19) + expr + id@(2:19-2:20)='t' + ')'@(2:20-2:21) + ';'@(2:21-2:22) + stmt_assign + id@(2:23-2:24)='k' + '='@(2:24-2:25) + expr + id@(2:25-2:26)='u' + ';'@(2:26-2:27) + '}'@(2:28-2:29) + Eof@(3:1-3:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt2.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.input.res new file mode 100644 index 0000000..664d772 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.input.res @@ -0,0 +1,18 @@ +T_Id@1,1:x +TAnonymous@1,3:= +T_Id@1,5:y +TAnonymous@1,6:; +TAnonymous@2,1:while +TAnonymous@2,7:( +T_Id@2,8:z +TAnonymous@2,9:) +TAnonymous@2,11:{ +TAnonymous@2,13:print +T_Id@2,19:t +TAnonymous@2,20:; +T_Id@2,22:k +TAnonymous@2,23:= +T_Id@2,24:u +TAnonymous@2,25:; +TAnonymous@2,27:} +TEnd@3,1: diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.res new file mode 100644 index 0000000..e3aa78f --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.alt3.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Parser' id '=' alts on token '('@(20:8-20:9) +NParserError@(20:8-20:9)='(' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.input.res new file mode 100644 index 0000000..40503ba --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.input.res @@ -0,0 +1,32 @@ +Start + prog + Nodes + stmt_assign + id@(1:1-1:2)='x' + '='@(1:3-1:4) + expr + id@(1:5-1:6)='y' + ';'@(1:6-1:7) + stmt_while + 'while'@(2:1-2:6) + '('@(2:7-2:8) + expr + id@(2:8-2:9)='z' + ')'@(2:9-2:10) + '{'@(2:11-2:12) + Nodes + stmt_print + 'print'@(2:13-2:18) + '('@(2:18-2:19) + expr + id@(2:19-2:20)='t' + ')'@(2:20-2:21) + ';'@(2:21-2:22) + stmt_assign + id@(2:23-2:24)='k' + '='@(2:24-2:25) + expr + id@(2:25-2:26)='u' + ';'@(2:26-2:27) + '}'@(2:28-2:29) + Eof@(3:1-3:1)='' diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-instructions.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.input.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.input.res new file mode 100644 index 0000000..4beb812 --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.input.res @@ -0,0 +1,10 @@ +TAnonymous@1,1:( +TAnonymous@1,2:( +T_Num@1,3:0 +TAnonymous@1,4:x +TAnonymous@1,5:, +T_Num@1,6:0 +TAnonymous@1,7:y +TAnonymous@1,8:) +TAnonymous@1,9:, +1,10. Syntax error: Unexpected character ' '. diff --git a/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.res b/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.res new file mode 100644 index 0000000..8d7cebd --- /dev/null +++ b/contrib/nitcc/t/sav/inf5000-06-grammaire2-polygone.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Parser' id '=' alts on token '('@(8:18-8:19) +NParserError@(8:18-8:19)='(' diff --git a/contrib/nitcc/t/sav/json.res b/contrib/nitcc/t/sav/json.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lalr.res b/contrib/nitcc/t/sav/lalr.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-c-comment.alt1.res b/contrib/nitcc/t/sav/lexer-c-comment.alt1.res new file mode 100644 index 0000000..deece4b --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-c-comment.alt1.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(9:16-9:16)='S' +NLexerError@(9:16-9:16)='S' diff --git a/contrib/nitcc/t/sav/lexer-c-comment.alt2.res b/contrib/nitcc/t/sav/lexer-c-comment.alt2.res new file mode 100644 index 0000000..b835c24 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-c-comment.alt2.res @@ -0,0 +1 @@ +Not Yet Implemented Error: '-' only works on single char diff --git a/contrib/nitcc/t/sav/lexer-c-comment.alt3.res b/contrib/nitcc/t/sav/lexer-c-comment.alt3.res new file mode 100644 index 0000000..8cbbfa8 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-c-comment.alt3.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' '(' re on token NLexerError@(11:26-11:27)='Lo' +NLexerError@(11:26-11:27)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-c-comment.alt4.res b/contrib/nitcc/t/sav/lexer-c-comment.alt4.res new file mode 100644 index 0000000..d8fd238 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-c-comment.alt4.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' '(' re on token NLexerError@(12:27-12:27)='E' +NLexerError@(12:27-12:27)='E' diff --git a/contrib/nitcc/t/sav/lexer-c-comment.res b/contrib/nitcc/t/sav/lexer-c-comment.res new file mode 100644 index 0000000..f66dc98 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-c-comment.res @@ -0,0 +1 @@ +ERROR: Conflicting tokens: com1 com2 diff --git a/contrib/nitcc/t/sav/lexer-errors.alt1.res b/contrib/nitcc/t/sav/lexer-errors.alt1.res new file mode 100644 index 0000000..dc6af8c --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt1.res @@ -0,0 +1 @@ +ERROR: Empty tokens a diff --git a/contrib/nitcc/t/sav/lexer-errors.alt2.res b/contrib/nitcc/t/sav/lexer-errors.alt2.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-errors.alt3.res b/contrib/nitcc/t/sav/lexer-errors.alt3.res new file mode 100644 index 0000000..6f17e3b --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt3.res @@ -0,0 +1 @@ +Error: circular regular expression a. diff --git a/contrib/nitcc/t/sav/lexer-errors.alt4.res b/contrib/nitcc/t/sav/lexer-errors.alt4.res new file mode 100644 index 0000000..6f17e3b --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt4.res @@ -0,0 +1 @@ +Error: circular regular expression a. diff --git a/contrib/nitcc/t/sav/lexer-errors.alt5.res b/contrib/nitcc/t/sav/lexer-errors.alt5.res new file mode 100644 index 0000000..38d2860 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt5.res @@ -0,0 +1 @@ +Error: unknown name fail diff --git a/contrib/nitcc/t/sav/lexer-errors.alt6.res b/contrib/nitcc/t/sav/lexer-errors.alt6.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-errors.alt7.res b/contrib/nitcc/t/sav/lexer-errors.alt7.res new file mode 100644 index 0000000..88facbb --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt7.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(10:16-10:17)='Lo' +NLexerError@(10:16-10:17)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-errors.alt8.res b/contrib/nitcc/t/sav/lexer-errors.alt8.res new file mode 100644 index 0000000..38d2860 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.alt8.res @@ -0,0 +1 @@ +Error: unknown name fail diff --git a/contrib/nitcc/t/sav/lexer-errors.res b/contrib/nitcc/t/sav/lexer-errors.res new file mode 100644 index 0000000..866a8f6 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-errors.res @@ -0,0 +1 @@ +Error: unknown name a diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.input.res b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.input.res new file mode 100644 index 0000000..2b5621c --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.input.res @@ -0,0 +1,5 @@ +T_Anb@1,1:a +T_A@1,2:a +T_B@1,3:b +T_B@1,4:b +TEnd@2,1: diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.res b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.res new file mode 100644 index 0000000..94e5458 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.alt1.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(4:9-4:10)='Lo' +NLexerError@(4:9-4:10)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.res b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.res new file mode 100644 index 0000000..94e5458 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest-and-priority.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(4:9-4:10)='Lo' +NLexerError@(4:9-4:10)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.input.res b/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.input.res new file mode 100644 index 0000000..12dc63d --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.input.res @@ -0,0 +1,4 @@ +T_B@1,1:ab +T_B@1,3:ab +T_A@1,5:a +1,6. Syntax error: Unexpected character 'c'. diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.res b/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.res new file mode 100644 index 0000000..d39b7be --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest.alt1.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(3:10-3:11)='Lo' +NLexerError@(3:10-3:11)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-implicit-longest.res b/contrib/nitcc/t/sav/lexer-implicit-longest.res new file mode 100644 index 0000000..b5b5d7b --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-implicit-longest.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(3:9-3:10)='Lo' +NLexerError@(3:9-3:10)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-markers.alt1.input.res b/contrib/nitcc/t/sav/lexer-markers.alt1.input.res new file mode 100644 index 0000000..32aae2f --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-markers.alt1.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:6)='abac' +Nodes + t_0 + a@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-markers.alt1.res b/contrib/nitcc/t/sav/lexer-markers.alt1.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-markers.alt2.input.res b/contrib/nitcc/t/sav/lexer-markers.alt2.input.res new file mode 100644 index 0000000..d0d504b --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-markers.alt2.input.res @@ -0,0 +1,4 @@ +NParserError@(1:6-1:7)='a' +Nodes + t_1 + b@(1:1-1:6)='aabac' diff --git a/contrib/nitcc/t/sav/lexer-markers.alt2.res b/contrib/nitcc/t/sav/lexer-markers.alt2.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-markers.input.res b/contrib/nitcc/t/sav/lexer-markers.input.res new file mode 100644 index 0000000..32aae2f --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-markers.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:6)='abac' +Nodes + t_0 + a@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-markers.res b/contrib/nitcc/t/sav/lexer-markers.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt1.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt1.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt1.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt1.res b/contrib/nitcc/t/sav/lexer-precedences.alt1.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt10.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt10.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt10.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt10.res b/contrib/nitcc/t/sav/lexer-precedences.alt10.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt2.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt2.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt2.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt2.res b/contrib/nitcc/t/sav/lexer-precedences.alt2.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt3.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt3.input.res new file mode 100644 index 0000000..ab653e5 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt3.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_1 + xb@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt3.res b/contrib/nitcc/t/sav/lexer-precedences.alt3.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt4.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt4.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt4.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt4.res b/contrib/nitcc/t/sav/lexer-precedences.alt4.res new file mode 100644 index 0000000..6a70780 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt4.res @@ -0,0 +1 @@ +ERROR: Conflicting tokens: xa xb diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt5.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt5.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt5.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt5.res b/contrib/nitcc/t/sav/lexer-precedences.alt5.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt6.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt6.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt6.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt6.res b/contrib/nitcc/t/sav/lexer-precedences.alt6.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt7.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt7.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt7.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt7.res b/contrib/nitcc/t/sav/lexer-precedences.alt7.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt8.res b/contrib/nitcc/t/sav/lexer-precedences.alt8.res new file mode 100644 index 0000000..c7cef22 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt8.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' '(' re on token NLexerError@(6:18-6:19)='Lo' +NLexerError@(6:18-6:19)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt9.input.res b/contrib/nitcc/t/sav/lexer-precedences.alt9.input.res new file mode 100644 index 0000000..4b0c2ea --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.alt9.input.res @@ -0,0 +1,4 @@ +NParserError@(1:2-1:3)='a' +Nodes + t_0 + xa@(1:1-1:2)='a' diff --git a/contrib/nitcc/t/sav/lexer-precedences.alt9.res b/contrib/nitcc/t/sav/lexer-precedences.alt9.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lexer-precedences.res b/contrib/nitcc/t/sav/lexer-precedences.res new file mode 100644 index 0000000..866a8f6 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-precedences.res @@ -0,0 +1 @@ +Error: unknown name a diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest.alt1.res b/contrib/nitcc/t/sav/lexer-shortest-longest.alt1.res new file mode 100644 index 0000000..0e9fe66 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest.alt1.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(6:22-6:23)='Lo' +NLexerError@(6:22-6:23)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest.alt2.res b/contrib/nitcc/t/sav/lexer-shortest-longest.alt2.res new file mode 100644 index 0000000..0e9fe66 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest.alt2.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(6:22-6:23)='Lo' +NLexerError@(6:22-6:23)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest.alt3.res b/contrib/nitcc/t/sav/lexer-shortest-longest.alt3.res new file mode 100644 index 0000000..0e9fe66 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest.alt3.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(6:22-6:23)='Lo' +NLexerError@(6:22-6:23)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest.input.res b/contrib/nitcc/t/sav/lexer-shortest-longest.input.res new file mode 100644 index 0000000..87a3bbb --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest.input.res @@ -0,0 +1,5 @@ +T_Ab@1,1:ab +T_L@1,3:a +T_Ab@1,4:ab +T_L@1,6:a +TEnd@2,1: diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest.res b/contrib/nitcc/t/sav/lexer-shortest-longest.res new file mode 100644 index 0000000..0e9fe66 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' re on token NLexerError@(6:22-6:23)='Lo' +NLexerError@(6:22-6:23)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.input.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.input.res new file mode 100644 index 0000000..c0167f1 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.input.res @@ -0,0 +1,3 @@ +T_Sa@1,1:a +T_A@1,2:ab +TEnd@2,1: diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.res new file mode 100644 index 0000000..81db0c3 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt1.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(4:6-4:7)='Lo' +NLexerError@(4:6-4:7)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt2.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt2.res new file mode 100644 index 0000000..81db0c3 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt2.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(4:6-4:7)='Lo' +NLexerError@(4:6-4:7)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.input.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.input.res new file mode 100644 index 0000000..32655e1 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.input.res @@ -0,0 +1,3 @@ +T_Sa@1,1:a +T_La@1,2:ab +TEnd@2,1: diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.res new file mode 100644 index 0000000..81db0c3 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt3.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(4:6-4:7)='Lo' +NLexerError@(4:6-4:7)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.alt4.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt4.res new file mode 100644 index 0000000..81db0c3 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.alt4.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(4:6-4:7)='Lo' +NLexerError@(4:6-4:7)='Lo' diff --git a/contrib/nitcc/t/sav/lexer-shortest-longest2.res b/contrib/nitcc/t/sav/lexer-shortest-longest2.res new file mode 100644 index 0000000..81db0c3 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer-shortest-longest2.res @@ -0,0 +1,2 @@ +* parse error in state 'Grammar' id ';' 'Lexer' id '=' on token NLexerError@(4:6-4:7)='Lo' +NLexerError@(4:6-4:7)='Lo' diff --git a/contrib/nitcc/t/sav/lexer_conflict_token.res b/contrib/nitcc/t/sav/lexer_conflict_token.res new file mode 100644 index 0000000..438487c --- /dev/null +++ b/contrib/nitcc/t/sav/lexer_conflict_token.res @@ -0,0 +1 @@ +ERROR: Conflicting tokens: a b diff --git a/contrib/nitcc/t/sav/lexer_empty_token.res b/contrib/nitcc/t/sav/lexer_empty_token.res new file mode 100644 index 0000000..a22914d --- /dev/null +++ b/contrib/nitcc/t/sav/lexer_empty_token.res @@ -0,0 +1 @@ +ERROR: Empty tokens b a diff --git a/contrib/nitcc/t/sav/lexer_features.input.res b/contrib/nitcc/t/sav/lexer_features.input.res new file mode 100644 index 0000000..ecd49a8 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer_features.input.res @@ -0,0 +1,9 @@ +T_Identifier@1,1:i +TAnonymous@1,3:if +T_Identifier@1,6:iff +T_Identifier@1,10:ifff +T_Decimal@2,1:70 +T_Zero@3,1:zero +T_Hex@4,1:0xFFff +T_IpAddress@5,1:192.168.0.1 +TEnd@6,1: diff --git a/contrib/nitcc/t/sav/lexer_features.input2.res b/contrib/nitcc/t/sav/lexer_features.input2.res new file mode 100644 index 0000000..7f02009 --- /dev/null +++ b/contrib/nitcc/t/sav/lexer_features.input2.res @@ -0,0 +1,2 @@ +T_Decimal@1,1:10 +1,3. Syntax error: Unexpected character '.'. diff --git a/contrib/nitcc/t/sav/lexer_features.res b/contrib/nitcc/t/sav/lexer_features.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/lr1.res b/contrib/nitcc/t/sav/lr1.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/lr1.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/minilang.res b/contrib/nitcc/t/sav/minilang.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/mixed_list.res b/contrib/nitcc/t/sav/mixed_list.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/modif.input1.res b/contrib/nitcc/t/sav/modif.input1.res new file mode 100644 index 0000000..3f7ce7d --- /dev/null +++ b/contrib/nitcc/t/sav/modif.input1.res @@ -0,0 +1,5 @@ +Start + p + 'a'@(1:1-1:2) + 'a'@(1:2-1:3) + Eof@(1:3-1:3)='' diff --git a/contrib/nitcc/t/sav/modif.input2.res b/contrib/nitcc/t/sav/modif.input2.res new file mode 100644 index 0000000..3a89b3e --- /dev/null +++ b/contrib/nitcc/t/sav/modif.input2.res @@ -0,0 +1,25 @@ +Start + p + 'a'@(1:1-1:2) + Nodes + q + 'b'@(1:2-1:3) + Nodes + r + 'c'@(1:3-1:4) + 'c'@(1:4-1:5) + 'b'@(1:5-1:6) + q + 'b'@(1:6-1:7) + Nodes + r + 'c'@(1:7-1:8) + 'c'@(1:8-1:9) + r + 'c'@(1:9-1:10) + s + 'd'@(1:10-1:11) + 'c'@(1:11-1:12) + 'b'@(1:12-1:13) + 'a'@(1:13-1:14) + Eof@(1:14-1:14)='' diff --git a/contrib/nitcc/t/sav/modif.input3.res b/contrib/nitcc/t/sav/modif.input3.res new file mode 100644 index 0000000..efaf7c5 --- /dev/null +++ b/contrib/nitcc/t/sav/modif.input3.res @@ -0,0 +1,4 @@ +NParserError@(1:3-1:4)='b' +Nodes + 'a'@(1:1-1:2) + 'b'@(1:2-1:3) diff --git a/contrib/nitcc/t/sav/modif.input4.res b/contrib/nitcc/t/sav/modif.input4.res new file mode 100644 index 0000000..c333c96 --- /dev/null +++ b/contrib/nitcc/t/sav/modif.input4.res @@ -0,0 +1,7 @@ +NParserError@(1:5-1:6)='d' +Nodes + 'a'@(1:1-1:2) + 'b'@(1:2-1:3) + 'c'@(1:3-1:4) + s + 'd'@(1:4-1:5) diff --git a/contrib/nitcc/t/sav/modif.res b/contrib/nitcc/t/sav/modif.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/nit_expr.res b/contrib/nitcc/t/sav/nit_expr.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/nit_expr.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/not_lalr.res b/contrib/nitcc/t/sav/not_lalr.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/not_lalr.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/not_slr.res b/contrib/nitcc/t/sav/not_slr.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/pri.res b/contrib/nitcc/t/sav/pri.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/pri.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/priority.res b/contrib/nitcc/t/sav/priority.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/priority.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/qualified.res b/contrib/nitcc/t/sav/qualified.res new file mode 100644 index 0000000..05b05f7 --- /dev/null +++ b/contrib/nitcc/t/sav/qualified.res @@ -0,0 +1 @@ +Error: there is conflicts diff --git a/contrib/nitcc/t/sav/trans.input.res b/contrib/nitcc/t/sav/trans.input.res new file mode 100644 index 0000000..ee9a31b --- /dev/null +++ b/contrib/nitcc/t/sav/trans.input.res @@ -0,0 +1,7 @@ +'x'@(1:1-1:2) +'x'@(1:2-1:3) +'y'@(1:3-1:4) +'y'@(1:4-1:5) +'x'@(1:5-1:6) +'y'@(1:6-1:7) +NLexerError@(1:7-1:7)='\n' diff --git a/contrib/nitcc/t/sav/trans.res b/contrib/nitcc/t/sav/trans.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/sav/trans_inline.input.res b/contrib/nitcc/t/sav/trans_inline.input.res new file mode 100644 index 0000000..67e695f --- /dev/null +++ b/contrib/nitcc/t/sav/trans_inline.input.res @@ -0,0 +1,7 @@ +'a'@(1:1-1:2) +'b'@(1:2-1:3) +'x'@(1:3-1:4) +'y'@(1:4-1:5) +'c'@(1:5-1:6) +'d'@(1:6-1:7) +NLexerError@(1:7-1:7)='\n' diff --git a/contrib/nitcc/t/sav/trans_inline.res b/contrib/nitcc/t/sav/trans_inline.res new file mode 100644 index 0000000..e69de29 diff --git a/contrib/nitcc/t/t b/contrib/nitcc/t/t new file mode 100755 index 0000000..14669a6 --- /dev/null +++ b/contrib/nitcc/t/t @@ -0,0 +1,139 @@ +#!/bin/bash + +# This file is part of Nit ( http://nitlanguage.org ). +# +# See the NOTICE file distributed with this work for copyright information. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This program is used to perform regression tests of nitcc. + +NITCC=../nitcc +NITC=../../../bin/nitc + +mkdir alt out 2>/dev/null + +if test "x$#" = "x0" +then + echo usage: `basename $0` [-v] grammar-files* + exit +fi + + +verbose=false +stop=false +while [ $stop = false ]; do + case $1 in + -v) verbose=true; shift;; + *) stop=true + esac +done + +# empty tap output +tap="tap.output" +>"$tap" +tapcount=0 + +differ() { + tapcount=$((tapcount + 1)) + r="$1" + if test \! -f "sav/$r" + then + if test -s "out/$r" + then + echo "[***no sav***] cp 'out/$r' sav/" + test $verbose = true && { cat "out/$r" ; echo ; } + echo >>"$tap" "not ok $tapcount - $name # TODO no sav" + else + echo "[0K]" + echo >>"$tap" "ok $tapcount - $name" + fi + elif diff "sav/$r" "out/$r" >/dev/null + then + echo "[OK]" + echo >>"$tap" "ok $tapcount - $name" + else + echo "[******failed******] diff -u {sav,out}/$r" + test $verbose = true && { diff -u "sav/$r" "out/$r" ; echo ; } + echo >>"$tap" "not ok $tapcount - $name" + fi +} + +for f in "$@" +do + for a in "$f" `./alterner.pl $f` + do + cla="" + langname="" + echo -n "* $a: " + bn=`basename "$a" .sablecc` + res="$bn".res + $NITCC "$a" >"out/$bn.nitcc.log" 2>&1 + if test $? != 0 + then + echo -n "!nitcc " + else + t=`grep -o '[^ ]*_test_parser' < "out/$bn.nitcc.log"` + if test -f "${t}.nit" + then + echo -n ". " + $NITC -I .. "${t}.nit" >/dev/null 2>&1 + if test $? != 0 + then + echo -n "!nitc " + else + echo -n ". " + cla="${t}" + langname="${t/_test_parser}" + fi + else + echo -n "!res " + echo + tapcount=$((tapcount + 1)) + echo >>"$tap" "not ok $tapcount - $a # TODO no res" + continue + fi + fi + + grep -i "error" "out/$bn.nitcc.log" > "out/$res" + name="$a" + differ $res + + if test \! -z $cla + then + bf=`basename "$f" .sablecc` + for i in "$bf".input* + do + test -f $i || { echo " - no input: $i" ; continue ; } + ni=${i#$bf} + resi="$bn$ni".res + rm "$langname.ast.out" 2>/dev/null + echo -n " - $i: " + ./"$cla" "$i" > "out/$bn.$ni.log" + if test $? != 0 + then + echo -n "!run " + else + echo -n ". " + fi + + cp "$langname.ast.out" "out/$resi" + name="$a $i" + differ "$resi" + done + fi + done +done + +echo >>"$tap" "1..$tapcount" +#prove --formatter=TAP::Formatter::JUnit /bin/cat :: tap.output > tap.xml diff --git a/contrib/nitcc/t/trans.sablecc b/contrib/nitcc/t/trans.sablecc new file mode 100644 index 0000000..494e866 --- /dev/null +++ b/contrib/nitcc/t/trans.sablecc @@ -0,0 +1,7 @@ +Grammar trans; + +Parser + +a = a a2 | a2; +a2 {-> a} = 'x' | a3 {-> a3}; +a3 {-> a} = 'y'; diff --git a/contrib/nitcc/t/trans_inline.sablecc b/contrib/nitcc/t/trans_inline.sablecc new file mode 100644 index 0000000..b380d65 --- /dev/null +++ b/contrib/nitcc/t/trans_inline.sablecc @@ -0,0 +1,6 @@ +Grammar trans_inline; + +Parser + +p = 'a' 'b' q_inline 'c' 'd' ; +q_inline = 'x' 'y' ; -- 1.7.9.5