Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-corinthia
diff --git a/experiments/flat/grammars/arithmetic.flat b/experiments/flat/grammars/arithmetic.flat
new file mode 100644
index 0000000..6f9c1e1
--- /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 : $Add(Factor PLUS Term)
+ | $Sub(Factor MINUS Term)
+ | Factor;
+Factor : $Mul(Primary TIMES Factor)
+ | $Div(Primary SLASH Factor)
+ | Primary;
+Primary : $Ident(ID)
+ | $Integer(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")*);
diff --git a/experiments/flat/grammars/flat.flat b/experiments/flat/grammars/flat.flat
index bf6e794..4fe4293 100644
--- a/experiments/flat/grammars/flat.flat
+++ b/experiments/flat/grammars/flat.flat
@@ -6,6 +6,7 @@
Suffix : Primary (QUESTION | STAR | PLUS)?;
Primary : Identifier !COLON
| DOLLAR OPEN Expression CLOSE
+ | DOLLAR Identifier OPEN Expression CLOSE
| OPEN Expression CLOSE
| Literal
| Class
diff --git a/experiments/flat/src/BuildGrammar.c b/experiments/flat/src/BuildGrammar.c
index 7425878..b34a7aa 100644
--- a/experiments/flat/src/BuildGrammar.c
+++ b/experiments/flat/src/BuildGrammar.c
@@ -303,15 +303,25 @@
return ExpressionNewString(result);
}
case 2: {
+ assert(isSequence(choice,5));
+ Term *ident = TermChildAt(choice,1);
+ char *label = identifierString(builder,ident);
+ Term *expression = TermChildAt(choice,3);
+ Expression *result = buildExpression(builder,expression);
+ result = ExpressionNewLabel(label,result);
+ free(label);
+ return result;
+ }
+ case 3: {
assert(isSequence(choice,3));
Term *expression = TermChildAt(choice,1);
return buildExpression(builder,expression);
}
- case 3:
- return buildLiteral(builder,choice);
case 4:
- return buildClass(builder,choice);
+ return buildLiteral(builder,choice);
case 5:
+ return buildClass(builder,choice);
+ case 6:
return buildDot(builder,choice);
default:
assert(!"Invalid choice for Primary");
@@ -474,6 +484,8 @@
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
diff --git a/experiments/flat/src/Builtin.c b/experiments/flat/src/Builtin.c
index ce060cb..291272b 100644
--- a/experiments/flat/src/Builtin.c
+++ b/experiments/flat/src/Builtin.c
@@ -88,6 +88,7 @@
// Primary : Identifier !COLON
// | DOLLAR OPEN Expression CLOSE
+ // | DOLLAR Identifier OPEN Expression CLOSE
// | OPEN Expression CLOSE
// | Literal
// | Class
@@ -95,6 +96,7 @@
GrammarDefine(gram,"Primary",
choice(seq(ref("Identifier"),not(ref("COLON"))),
seq(ref("DOLLAR"),ref("OPEN"),ref("Expression"),ref("CLOSE")),
+ seq(ref("DOLLAR"),ref("Identifier"),ref("OPEN"),ref("Expression"),ref("CLOSE")),
seq(ref("OPEN"),ref("Expression"),ref("CLOSE")),
ref("Literal"),
ref("Class"),
diff --git a/experiments/flat/src/Builtin.h b/experiments/flat/src/Builtin.h
index 76d3f38..14a2f71 100644
--- a/experiments/flat/src/Builtin.h
+++ b/experiments/flat/src/Builtin.h
@@ -31,6 +31,7 @@
* Suffix : Primary (QUESTION | STAR | PLUS)?;
* Primary : Identifier !COLON
* | DOLLAR OPEN Expression CLOSE
+ * | DOLLAR Identifier OPEN Expression CLOSE
* | OPEN Expression CLOSE
* | Literal
* | Class
diff --git a/experiments/flat/src/Expression.c b/experiments/flat/src/Expression.c
index ad2fc2e..9af0d2c 100644
--- a/experiments/flat/src/Expression.c
+++ b/experiments/flat/src/Expression.c
@@ -61,6 +61,8 @@
return "Range";
case StringExpr:
return "String";
+ case LabelExpr:
+ return "Label";
}
return "?";
}
@@ -197,6 +199,17 @@
return expr;
}
+Expression *ExpressionNewLabel(const char *label, Expression *child)
+{
+ assert(child != NULL);
+ Expression *expr = (Expression *)calloc(1,sizeof(Expression)+1*sizeof(Expression *));
+ expr->kind = LabelExpr;
+ expr->value = strdup(label);
+ expr->count = 1;
+ expr->children[0] = child;
+ return expr;
+}
+
void ExpressionFree(Expression *expr)
{
if (expr == NULL)
@@ -232,6 +245,7 @@
case DotExpr:
return 5;
case StringExpr:
+ case LabelExpr:
return 6;
case RangeExpr:
return 7;
@@ -329,6 +343,12 @@
ExpressionPrint(ExprStringChild(expr),highestPrecedence,NULL);
printf(")");
break;
+ case LabelExpr:
+ printf("$%s(",ExprLabelIdent(expr));
+ highestPrecedence = 1; // because of brackets
+ ExpressionPrint(ExprLabelChild(expr),highestPrecedence,NULL);
+ printf(")");
+ break;
}
if (brackets)
printf(")");
@@ -494,3 +514,23 @@
assert(expr->children[0] != NULL);
return expr->children[0];
}
+
+// Label
+
+const char *ExprLabelIdent(Expression *expr)
+{
+ assert(expr->kind == LabelExpr);
+ assert(expr->count == 1);
+ assert(expr->value != NULL);
+ assert(expr->children[0] != NULL);
+ return expr->value;
+}
+
+Expression *ExprLabelChild(Expression *expr)
+{
+ assert(expr->kind == LabelExpr);
+ assert(expr->count == 1);
+ assert(expr->value != NULL);
+ assert(expr->children[0] != NULL);
+ return expr->children[0];
+}
diff --git a/experiments/flat/src/Expression.h b/experiments/flat/src/Expression.h
index 1058be0..3d81460 100644
--- a/experiments/flat/src/Expression.h
+++ b/experiments/flat/src/Expression.h
@@ -73,6 +73,14 @@
* StringExpr - Instructs the parser to construct a single node in the parse tree representing
* everything within the child expression. Doesn't have any effect on what is or isn't accepted
* by the parser.
+ *
+ * LabelExpr - Instructs the parser to construct a label node in the parse tree, indicating
+ * semantically important information. Many nodes in the parse tree are there simply because
+ * they formed part of the call tree used during parsing, but do not necessarily have any
+ * use for subsequent analysis of the tree. Label expressions are intended to, in the future,
+ * allow us to have simpler trees which only contain the information necessary for analysing
+ * a syntax tree. Like String expressions, Label expressions do not have any effect on what is or
+ * isn't accepted by the parser.
*/
typedef enum {
@@ -89,6 +97,7 @@
DotExpr,
RangeExpr,
StringExpr,
+ LabelExpr,
} ExprKind;
typedef struct Expression Expression;
@@ -108,6 +117,7 @@
Expression *ExpressionNewDot(void);
Expression *ExpressionNewRange(int lo, int hi);
Expression *ExpressionNewString(Expression *child);
+Expression *ExpressionNewLabel(const char *label, Expression *child);
void ExpressionFree(Expression *expr);
void ExpressionPrint(Expression *expr, int highestPrecedence, const char *indent);
@@ -153,3 +163,8 @@
// String
Expression *ExprStringChild(Expression *expr);
+
+// Label
+
+const char *ExprLabelIdent(Expression *expr);
+Expression *ExprLabelChild(Expression *expr);
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 @@
free(prefix);
}
+
+const char *GrammarFirstRuleName(Grammar *gram)
+{
+ if (gram->defList == NULL)
+ return NULL;
+ else
+ return gram->defList->name;
+}
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 @@
Expression *GrammarLookup(Grammar *gram, const char *name);
void GrammarResolve(Grammar *gram);
void GrammarPrint(Grammar *gram);
+const char *GrammarFirstRuleName(Grammar *gram);
diff --git a/experiments/flat/src/Parser.c b/experiments/flat/src/Parser.c
index 74c1e28..5c76a1a 100644
--- a/experiments/flat/src/Parser.c
+++ b/experiments/flat/src/Parser.c
@@ -212,6 +212,12 @@
// (which can be recovered from the input, and the start and end fields of the term).
return TermNew(expr,startPos,p->pos,NULL);
}
+ case LabelExpr: {
+ Term *term = parseExpr(p,ExprLabelChild(expr));
+ if (term == NULL)
+ return NULL;
+ return TermNew(expr,startPos,p->pos,TermListNew(term,NULL));
+ }
}
assert(!"unknown expression type");
return NULL;
diff --git a/experiments/flat/src/Term.c b/experiments/flat/src/Term.c
index e3fc44b..f0369eb 100644
--- a/experiments/flat/src/Term.c
+++ b/experiments/flat/src/Term.c
@@ -105,6 +105,9 @@
case IdentExpr:
printf("%s %s\n",ExprKindAsString(ExpressionKind(term->type)),ExprIdentValue(term->type));
break;
+ case LabelExpr:
+ printf("%s %s\n",ExprKindAsString(ExpressionKind(term->type)),ExprLabelIdent(term->type));
+ break;
case LitExpr:
case RangeExpr:
case DotExpr:
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 @@
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,28 +94,32 @@
GrammarFree(gram);
}
else if ((argc == 3) && !strcmp(argv[1],"-b")) {
- const char *filename = argv[2];
- char *input = readStringFromFile(filename);
- if (input == NULL) {
- perror(filename);
- exit(1);
- }
-
- Grammar *gram = GrammarNewBuiltin();
- Term *term = parse(gram,"Grammar",input,0,strlen(input));
- if (term == NULL) {
- fprintf(stderr,"%s: Parse failed\n",filename);
- exit(1);
- }
-
-
- Grammar *built = grammarFromTerm(term,input);
+ Grammar *built = grammarFromFile(argv[2]);
GrammarPrint(built);
-
- free(input);
- GrammarFree(gram);
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 *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,"");
+
+ free(inputStr);
+ GrammarFree(builtGrammar);
+ }
else {
printf("Usage:\n"
"\n"
@@ -109,6 +136,11 @@
"\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;