Fix infinite loops during table generation for left-recursive rules
Add function calls for arbitrary expressions and dot property access to javascript grammar
This commit is contained in:
parent
3f770ff3c3
commit
820b6f4020
7 changed files with 2824 additions and 2292 deletions
|
|
@ -68,6 +68,21 @@ describe("computing FIRST sets", []() {
|
|||
})));
|
||||
});
|
||||
});
|
||||
|
||||
describe("when there are left-recursive rules", [&]() {
|
||||
it("terminates", [&]() {
|
||||
Grammar grammar({
|
||||
{ "expression", choice({
|
||||
seq({ sym("expression"), sym("x") }),
|
||||
sym("y"),
|
||||
}) },
|
||||
});
|
||||
|
||||
AssertThat(first_set(sym("expression"), grammar), Equals(set<Symbol>({
|
||||
Symbol("y")
|
||||
})));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
END_TEST
|
||||
END_TEST
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "compiler_spec_helper.h"
|
||||
#include "compiler/build_tables/rule_can_be_blank.h"
|
||||
#include "compiler/prepared_grammar.h"
|
||||
|
||||
using namespace rules;
|
||||
using build_tables::rule_can_be_blank;
|
||||
|
|
@ -7,21 +8,63 @@ using build_tables::rule_can_be_blank;
|
|||
START_TEST
|
||||
|
||||
describe("checking if rules can be blank", [&]() {
|
||||
it("handles sequences", [&]() {
|
||||
rule_ptr rule = seq({
|
||||
choice({
|
||||
str("x"),
|
||||
blank(),
|
||||
}),
|
||||
str("y"),
|
||||
});
|
||||
rule_ptr rule;
|
||||
|
||||
AssertThat(rule_can_be_blank(rule), Equals(false));
|
||||
it("returns false for basic rules", [&]() {
|
||||
AssertThat(rule_can_be_blank(sym("x")), IsFalse());
|
||||
AssertThat(rule_can_be_blank(str("x")), IsFalse());
|
||||
AssertThat(rule_can_be_blank(pattern("x")), IsFalse());
|
||||
});
|
||||
|
||||
it("returns true for blanks", [&]() {
|
||||
AssertThat(rule_can_be_blank(blank()), IsTrue());
|
||||
});
|
||||
|
||||
it("returns true for repeats", [&]() {
|
||||
rule_ptr rule = repeat(str("x"));
|
||||
AssertThat(rule_can_be_blank(rule), Equals(true));
|
||||
AssertThat(rule_can_be_blank(repeat(str("x"))), IsTrue());
|
||||
});
|
||||
|
||||
it("returns true for choices iff one or more sides can be blank", [&]() {
|
||||
rule = choice({ sym("x"), blank() });
|
||||
AssertThat(rule_can_be_blank(rule), IsTrue());
|
||||
|
||||
rule = choice({ blank(), sym("x") });
|
||||
AssertThat(rule_can_be_blank(rule), IsTrue());
|
||||
|
||||
rule = choice({ sym("x"), sym("y") });
|
||||
AssertThat(rule_can_be_blank(rule), IsFalse());
|
||||
});
|
||||
|
||||
it("returns true for sequences iff both sides can be blank", [&]() {
|
||||
rule = seq({ blank(), str("x") });
|
||||
AssertThat(rule_can_be_blank(rule), IsFalse());
|
||||
|
||||
rule = seq({ str("x"), blank() });
|
||||
AssertThat(rule_can_be_blank(rule), IsFalse());
|
||||
|
||||
rule = seq({ blank(), choice({ sym("x"), blank() }) });
|
||||
AssertThat(rule_can_be_blank(rule), IsTrue());
|
||||
});
|
||||
|
||||
describe("checking recursively (by expanding non-terminals)", [&]() {
|
||||
PreparedGrammar grammar({
|
||||
{ "A", choice({
|
||||
seq({ sym("A"), sym("x") }),
|
||||
blank() }) },
|
||||
{ "B", choice({
|
||||
seq({ sym("B"), sym("y") }),
|
||||
sym("z") }) },
|
||||
}, {});
|
||||
|
||||
it("terminates for left-recursive rules that can be blank", [&]() {
|
||||
rule = sym("A");
|
||||
AssertThat(rule_can_be_blank(rule, grammar), IsTrue());
|
||||
});
|
||||
|
||||
it("terminates for left-recursive rules that can't be blank", [&]() {
|
||||
rule = sym("B");
|
||||
AssertThat(rule_can_be_blank(rule, grammar), IsFalse());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -56,15 +56,21 @@ else {
|
|||
==========================================
|
||||
parses named functions
|
||||
==========================================
|
||||
function doThis(argA, argB) {
|
||||
var x = argA;
|
||||
var x = {
|
||||
theMethod: function(argA, argB) {
|
||||
var x = argA;
|
||||
}
|
||||
};
|
||||
|
||||
doThis(5, 6);
|
||||
x.theMethod(5, 6);
|
||||
---
|
||||
(program
|
||||
(statement (function_expression
|
||||
(statement (assignment
|
||||
(identifier)
|
||||
(formal_parameters (identifier) (identifier))
|
||||
(statement_block (statement (assignment (identifier) (identifier))))))
|
||||
(statement (function_call (identifier) (number) (number))))
|
||||
(object (identifier) (function_expression
|
||||
(formal_parameters (identifier) (identifier))
|
||||
(statement_block (statement (assignment (identifier) (identifier))))))))
|
||||
(statement (function_call
|
||||
(property_access (identifier) (identifier))
|
||||
(number) (number))))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue