You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@corinthia.apache.org by pm...@apache.org on 2015/08/08 19:01:45 UTC

incubator-corinthia git commit: Flat: Support parsing using custom grammars

Repository: incubator-corinthia
Updated Branches:
  refs/heads/master 79101d29e -> 02c9f1d8a


Flat: Support parsing using custom grammars

Add the ability to use the flat command-line tool to specify both a
grammar file and an input which should be parsed using that grammar.
After a successful parse, the parse tree is printed to standard output.

This is what makes Flat a parser *interpreter*, rather than a parser
*generator*. There is no need for the an intermediate step of compiling
generated files as with many other parsing tools like Bison/Flex, ANTLR,
JavaCC, or Stratego/XT. We can (and probably will) choose to add code
generation as an optional feature later on, but it's not a fundamental
requirement.


Project: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/commit/02c9f1d8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/tree/02c9f1d8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-corinthia/diff/02c9f1d8

Branch: refs/heads/master
Commit: 02c9f1d8a0123cee8b5e6ca16b1d51e830ba7dc4
Parents: 79101d2
Author: Peter Kelly <pe...@uxproductivity.com>
Authored: Sat Aug 8 23:53:23 2015 +0700
Committer: Peter Kelly <pe...@uxproductivity.com>
Committed: Sat Aug 8 23:53:23 2015 +0700

----------------------------------------------------------------------
 experiments/flat/grammars/arithmetic.flat | 22 +++++++++
 experiments/flat/src/BuildGrammar.c       |  2 +
 experiments/flat/src/Grammar.c            |  8 ++++
 experiments/flat/src/Grammar.h            |  1 +
 experiments/flat/src/flat.c               | 62 +++++++++++++++++++-------
 5 files changed, 80 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/02c9f1d8/experiments/flat/grammars/arithmetic.flat
----------------------------------------------------------------------
diff --git a/experiments/flat/grammars/arithmetic.flat b/experiments/flat/grammars/arithmetic.flat
new file mode 100644
index 0000000..46e2e5d
--- /dev/null
+++ b/experiments/flat/grammars/arithmetic.flat
@@ -0,0 +1,22 @@
+# Note: The Term and Factor rules are right recursive. They are actually
+# supposed to be left recursive, but we don't support that yet.
+Start   : Expr !.;
+Expr    : Term;
+Term    : Factor PLUS Term
+        | Factor MINUS Term
+        | Factor;
+Factor  : Primary TIMES Factor
+        | Primary SLASH Factor
+        | Primary;
+Primary : ID
+        | INT
+        | OPEN Expr CLOSE;
+PLUS    : "+" Spacing;
+MINUS   : "-" Spacing;
+TIMES   : "*" Spacing;
+SLASH   : "/" Spacing;
+OPEN    : "(" Spacing;
+CLOSE   : ")" Spacing;
+ID      : $([a-zA-Z_] [a-zA-Z_0-9]*) Spacing;
+INT     : $([1-9] [0-9]*) Spacing;
+Spacing : $((" " | "\t" | "\r" | "\n")*);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/02c9f1d8/experiments/flat/src/BuildGrammar.c
----------------------------------------------------------------------
diff --git a/experiments/flat/src/BuildGrammar.c b/experiments/flat/src/BuildGrammar.c
index 7425878..ea546e3 100644
--- a/experiments/flat/src/BuildGrammar.c
+++ b/experiments/flat/src/BuildGrammar.c
@@ -474,6 +474,8 @@ static void buildGrammar(Builder *builder, Term *term)
         GrammarDefine(builder->gram,ruleName,ruleExpr);
         free(ruleName);
     }
+
+    GrammarResolve(builder->gram);
 }
 
 // This function creates a new Grammar object from the result of parsing a file usin the built-in

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/02c9f1d8/experiments/flat/src/Grammar.c
----------------------------------------------------------------------
diff --git a/experiments/flat/src/Grammar.c b/experiments/flat/src/Grammar.c
index f015dfb..6743953 100644
--- a/experiments/flat/src/Grammar.c
+++ b/experiments/flat/src/Grammar.c
@@ -131,3 +131,11 @@ void GrammarPrint(Grammar *gram)
 
     free(prefix);
 }
+
+const char *GrammarFirstRuleName(Grammar *gram)
+{
+    if (gram->defList == NULL)
+        return NULL;
+    else
+        return gram->defList->name;
+}

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/02c9f1d8/experiments/flat/src/Grammar.h
----------------------------------------------------------------------
diff --git a/experiments/flat/src/Grammar.h b/experiments/flat/src/Grammar.h
index e94e51b..f51bd18 100644
--- a/experiments/flat/src/Grammar.h
+++ b/experiments/flat/src/Grammar.h
@@ -28,3 +28,4 @@ void GrammarDefine(Grammar *gram, const char *name, Expression *expr);
 Expression *GrammarLookup(Grammar *gram, const char *name);
 void GrammarResolve(Grammar *gram);
 void GrammarPrint(Grammar *gram);
+const char *GrammarFirstRuleName(Grammar *gram);

http://git-wip-us.apache.org/repos/asf/incubator-corinthia/blob/02c9f1d8/experiments/flat/src/flat.c
----------------------------------------------------------------------
diff --git a/experiments/flat/src/flat.c b/experiments/flat/src/flat.c
index 8aa4f74..ee3c2bb 100644
--- a/experiments/flat/src/flat.c
+++ b/experiments/flat/src/flat.c
@@ -44,6 +44,29 @@ static char *readStringFromFile(const char *filename)
     return data;
 }
 
+static Grammar *grammarFromFile(const char *filename)
+{
+    char *input = readStringFromFile(filename);
+    if (input == NULL) {
+        perror(filename);
+        exit(1);
+    }
+
+    Grammar *flatGrammar = GrammarNewBuiltin();
+    Term *term = parse(flatGrammar,"Grammar",input,0,strlen(input));
+    if (term == NULL) {
+        fprintf(stderr,"%s: Parse failed\n",filename);
+        exit(1);
+    }
+
+    Grammar *builtGrammar = grammarFromTerm(term,input);
+
+    free(input);
+    GrammarFree(flatGrammar);
+
+    return builtGrammar;
+}
+
 int main(int argc, const char **argv)
 {
 
@@ -71,27 +94,31 @@ int main(int argc, const char **argv)
         GrammarFree(gram);
     }
     else if ((argc == 3) && !strcmp(argv[1],"-b")) {
-        const char *filename = argv[2];
-        char *input = readStringFromFile(filename);
-        if (input == NULL) {
-            perror(filename);
+        Grammar *built = grammarFromFile(argv[2]);
+        GrammarPrint(built);
+        GrammarFree(built);
+    }
+    else if (argc == 3) {
+        const char *grammarFilename = argv[1];
+        const char *inputFilename = argv[2];
+
+        char *inputStr = readStringFromFile(inputFilename);
+        if (inputStr == NULL) {
+            perror(inputFilename);
             exit(1);
         }
 
-        Grammar *gram = GrammarNewBuiltin();
-        Term *term = parse(gram,"Grammar",input,0,strlen(input));
-        if (term == NULL) {
-            fprintf(stderr,"%s: Parse failed\n",filename);
+        Grammar *builtGrammar = grammarFromFile(grammarFilename);
+        const char *firstRuleName = GrammarFirstRuleName(builtGrammar);
+        Term *inputTerm = parse(builtGrammar,firstRuleName,inputStr,0,strlen(inputStr));
+        if (inputTerm == NULL) {
+            fprintf(stderr,"%s: Parse failed\n",inputFilename);
             exit(1);
         }
+        TermPrint(inputTerm,inputStr,"");
 
-
-        Grammar *built = grammarFromTerm(term,input);
-        GrammarPrint(built);
-
-        free(input);
-        GrammarFree(gram);
-        GrammarFree(built);
+        free(inputStr);
+        GrammarFree(builtGrammar);
     }
     else {
         printf("Usage:\n"
@@ -109,6 +136,11 @@ int main(int argc, const char **argv)
                "\n"
                "    Parse FILENAME using the built-in PEG grammar, then use the resulting parse\n"
                "    tree to build a Grammar object, and print out the constructed grammar.\n"
+               "\n"
+               "flat GRAMMAR INPUT\n"
+               "\n"
+               "    Use the grammar defined in file GRAMMAR to parse the file INPUT, and print\n"
+               "    out the resulting parse tree\n"
                "\n");
 
         return 1;