All new
alle new
This commit is contained in:
1 parent
da64472251
commit
5b20adee48
1605 files changed
+396517
-1674
No files matched your search
+128
@@ -0,0 +1,128 @@
|
||||
var rules = require("./rules");
|
||||
var results = require("./parsing-results");
|
||||
|
||||
exports.parser = function(name, prefixRules, infixRuleBuilders) {
|
||||
var self = {
|
||||
rule: rule,
|
||||
leftAssociative: leftAssociative,
|
||||
rightAssociative: rightAssociative
|
||||
};
|
||||
|
||||
var infixRules = new InfixRules(infixRuleBuilders.map(createInfixRule));
|
||||
var prefixRule = rules.firstOf(name, prefixRules);
|
||||
|
||||
function createInfixRule(infixRuleBuilder) {
|
||||
return {
|
||||
name: infixRuleBuilder.name,
|
||||
rule: lazyRule(infixRuleBuilder.ruleBuilder.bind(null, self))
|
||||
};
|
||||
}
|
||||
|
||||
function rule() {
|
||||
return createRule(infixRules);
|
||||
}
|
||||
|
||||
function leftAssociative(name) {
|
||||
return createRule(infixRules.untilExclusive(name));
|
||||
}
|
||||
|
||||
function rightAssociative(name) {
|
||||
return createRule(infixRules.untilInclusive(name));
|
||||
}
|
||||
|
||||
function createRule(infixRules) {
|
||||
return apply.bind(null, infixRules);
|
||||
}
|
||||
|
||||
function apply(infixRules, tokens) {
|
||||
var leftResult = prefixRule(tokens);
|
||||
if (leftResult.isSuccess()) {
|
||||
return infixRules.apply(leftResult);
|
||||
} else {
|
||||
return leftResult;
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
};
|
||||
|
||||
function InfixRules(infixRules) {
|
||||
function untilExclusive(name) {
|
||||
return new InfixRules(infixRules.slice(0, ruleNames().indexOf(name)));
|
||||
}
|
||||
|
||||
function untilInclusive(name) {
|
||||
return new InfixRules(infixRules.slice(0, ruleNames().indexOf(name) + 1));
|
||||
}
|
||||
|
||||
function ruleNames() {
|
||||
return infixRules.map(function(rule) {
|
||||
return rule.name;
|
||||
});
|
||||
}
|
||||
|
||||
function apply(leftResult) {
|
||||
var currentResult;
|
||||
var source;
|
||||
while (true) {
|
||||
currentResult = applyToTokens(leftResult.remaining());
|
||||
if (currentResult.isSuccess()) {
|
||||
source = leftResult.source().to(currentResult.source());
|
||||
leftResult = results.success(
|
||||
currentResult.value()(leftResult.value(), source),
|
||||
currentResult.remaining(),
|
||||
source
|
||||
)
|
||||
} else if (currentResult.isFailure()) {
|
||||
return leftResult;
|
||||
} else {
|
||||
return currentResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyToTokens(tokens) {
|
||||
return rules.firstOf("infix", infixRules.map(function(infix) {
|
||||
return infix.rule;
|
||||
}))(tokens);
|
||||
}
|
||||
|
||||
return {
|
||||
apply: apply,
|
||||
untilExclusive: untilExclusive,
|
||||
untilInclusive: untilInclusive
|
||||
}
|
||||
}
|
||||
|
||||
exports.infix = function(name, ruleBuilder) {
|
||||
function map(func) {
|
||||
return exports.infix(name, function(parser) {
|
||||
var rule = ruleBuilder(parser);
|
||||
return function(tokens) {
|
||||
var result = rule(tokens);
|
||||
return result.map(function(right) {
|
||||
return function(left, source) {
|
||||
return func(left, right, source);
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
name: name,
|
||||
ruleBuilder: ruleBuilder,
|
||||
map: map
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: move into a sensible place and remove duplication
|
||||
var lazyRule = function(ruleBuilder) {
|
||||
var rule;
|
||||
return function(input) {
|
||||
if (!rule) {
|
||||
rule = ruleBuilder();
|
||||
}
|
||||
return rule(input);
|
||||
};
|
||||
};
|
||||
Reference in new issue
Block a user