Created
January 4, 2012 17:38
-
-
Save pocketberserker/1561122 to your computer and use it in GitHub Desktop.
JParsecでΣ演算
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public final class BinaryExpression implements Expression { | |
public final Expression left; | |
public final Op operator; | |
public final Expression right; | |
public BinaryExpression(Expression left, Op operator, Expression right) { | |
this.left = left; | |
this.operator = operator; | |
this.right = right; | |
} | |
public String toString() { | |
return "(" + operator.toString() + " " + left.toString() + " " + right.toString() + ")"; | |
} | |
@Override | |
public Double accept(ExpressionVisitor visitor) { | |
return visitor.visit(this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package parser; | |
import org.codehaus.jparsec.OperatorTable; | |
import org.codehaus.jparsec.Parser; | |
import org.codehaus.jparsec.Parsers; | |
import org.codehaus.jparsec.Scanners; | |
import org.codehaus.jparsec.Terminals; | |
import org.codehaus.jparsec.functors.Binary; | |
import org.codehaus.jparsec.functors.Unary; | |
import org.codehaus.jparsec.misc.Mapper; | |
import static org.codehaus.jparsec.misc.Mapper._; | |
import ast.*; | |
import ast.Number; | |
public class Calculator { | |
private static final String[] OPERATORS = { "+", "-", "*", "/", "(", ")", ":", ".." }; | |
private static final String[] KEYWORDS = { "sum", "i", "of" }; | |
private static final Terminals TERMS = Terminals.caseSensitive(OPERATORS, KEYWORDS); | |
private static final Parser<?> TOKENIZER = Parsers.or( | |
TERMS.tokenizer(), Terminals.DecimalLiteral.TOKENIZER); | |
private static final Parser<Expression> NUMBER = | |
curry(Number.class).sequence(Terminals.DecimalLiteral.PARSER); | |
private static final Parser<Expression> VARIABLE = | |
curry(Variable.class).sequence(TERMS.token("i").source()); | |
private static final Parser<Void> IGNORED = | |
Parsers.or(Scanners.JAVA_LINE_COMMENT, Scanners.JAVA_BLOCK_COMMENT, Scanners.WHITESPACES).skipMany(); | |
private static Parser<?> term(String... names) { | |
return _(TERMS.token(names)); | |
} | |
private static Mapper<Expression> curry(Class<? extends Expression> clazz, Object... args) { | |
return Mapper.<Expression>curry(clazz, args); | |
} | |
private static final Parser<Binary<Expression>> WHITESPACE_MUL = | |
term("+", "-", "*", "/").not().next(curry(BinaryExpression.class, Op.MUL).binary()); | |
private static Parser<Binary<Expression>> binary(String name, Op op) { | |
return term(name).next(curry(BinaryExpression.class, op).binary()); | |
} | |
private static Parser<Unary<Expression>> unary(String name, Op op) { | |
return term(name).next(curry(UnaryExpression.class, op).unary()); | |
} | |
private static Parser<Expression> sum( | |
Parser<Expression> init, Parser<Expression> max, Parser<Expression> expr) { | |
return curry(SumExpression.class).sequence( | |
term("sum"), _(term("i")), term(":"), init,term(".."), max, term("of"), expr); | |
} | |
static Parser<Expression> alithmetic() { | |
Parser.Reference<Expression> ref = Parser.newReference(); | |
Parser<Expression> unit = ref.lazy().between(term("("), term(")")).or(NUMBER).or(VARIABLE); | |
Parser<Expression> parser = new OperatorTable<Expression>() | |
.infixl(binary("+", Op.PLUS), 10) | |
.infixl(binary("-", Op.MINUS), 10) | |
.infixl(binary("*", Op.MUL).or(WHITESPACE_MUL), 20) | |
.infixl(binary("/", Op.DIV), 20) | |
.prefix(unary("+", Op.POS), 30) | |
.prefix(unary("-", Op.NEG), 30) | |
.build(unit); | |
ref.set(parser); | |
return parser; | |
} | |
static Parser<Expression> sumExpr() { | |
Parser.Reference<Expression> ref = Parser.newReference(); | |
Parser<Expression> unit = ref.lazy().or(NUMBER); | |
Parser<Expression> parser = sum(unit,unit,alithmetic()); | |
ref.set(parser); | |
return parser; | |
} | |
public static final Parser<Expression> EXPRESSION = alithmetic().from(TOKENIZER, IGNORED); | |
public static final Parser<Expression> SUMEXPR = sumExpr().from(TOKENIZER, IGNORED); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
import ast.BinaryExpression; | |
import ast.Expression; | |
import ast.Number; | |
import ast.SumExpression; | |
import ast.UnaryExpression; | |
import ast.Variable; | |
public class Eval implements ExpressionVisitor { | |
private Double variable; | |
@Override | |
public Double visit(Expression e) { | |
return e.accept(this); | |
} | |
@Override | |
public Double visit(BinaryExpression e) { | |
switch(e.operator) { | |
case PLUS: | |
return e.left.accept(this) + e.right.accept(this); | |
case MINUS: | |
return e.left.accept(this) - e.right.accept(this); | |
case MUL: | |
return e.left.accept(this) * e.right.accept(this); | |
case DIV: | |
return e.left.accept(this) / e.right.accept(this); | |
default: | |
throw new IllegalArgumentException(); | |
} | |
} | |
@Override | |
public Double visit(UnaryExpression e) { | |
switch(e.operator) { | |
case POS: | |
return e.expr.accept(this); | |
case NEG: | |
return - e.expr.accept(this); | |
default: | |
throw new IllegalArgumentException(); | |
} | |
} | |
@Override | |
public Double visit(Variable e) { | |
return variable; | |
} | |
@Override | |
public Double visit(Number e) { | |
return Double.parseDouble(e.number); | |
} | |
@Override | |
public Double visit(SumExpression e) { | |
double value = 0; | |
double init = e.init.accept(this); | |
double max = e.max.accept(this); | |
for(int i = (int)init; i <= max; ++i) { | |
variable = (double)i; | |
value += e.expr.accept(this); | |
} | |
return value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public interface Expression { | |
public Double accept(ExpressionVisitor visitor); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package visitor; | |
import ast.*; | |
import ast.Number; | |
public interface ExpressionVisitor { | |
public Double visit(Expression e); | |
public Double visit(BinaryExpression e); | |
public Double visit(UnaryExpression e); | |
public Double visit(Variable e); | |
public Double visit(Number e); | |
public Double visit(SumExpression e); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public final class Number implements Expression { | |
public final String number; | |
public Number(String number) { | |
this.number = number; | |
} | |
public String toString() { | |
return number; | |
} | |
@Override | |
public Double accept(ExpressionVisitor visitor) { | |
return visitor.visit(this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
public enum Op { | |
PLUS { | |
public String toString() { return "+"; } | |
}, | |
MINUS { | |
public String toString() { return "-"; } | |
}, | |
MUL { | |
public String toString() { return "*"; } | |
}, | |
DIV { | |
public String toString() { return "/"; } | |
}, | |
POS { | |
public String toString() { return "+"; } | |
}, | |
NEG { | |
public String toString() { return "-"; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public final class SumExpression implements Expression { | |
public final Number init; | |
public final Number max; | |
public final Expression expr; | |
public SumExpression(Number init, Number max, Expression expr) { | |
this.init = init; | |
this.max = max; | |
this.expr = expr; | |
} | |
public String toString() { | |
return "(sum " + init + " " + max + " " + expr.toString() + ")"; | |
} | |
@Override | |
public Double accept(ExpressionVisitor visitor) { | |
return visitor.visit(this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public final class UnaryExpression implements Expression { | |
public final Expression expr; | |
public final Op operator; | |
public UnaryExpression(Op oprator, Expression expr) { | |
this.operator = oprator; | |
this.expr = expr; | |
} | |
public String toString() { | |
return "(" + operator.toString() + " " + expr.toString() + ")"; | |
} | |
@Override | |
public Double accept(ExpressionVisitor visitor) { | |
return visitor.visit(this); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ast; | |
import visitor.ExpressionVisitor; | |
public final class Variable implements Expression { | |
public final String variable; | |
public Variable(String variable) { | |
this.variable = variable; | |
} | |
public String toString() { | |
return variable; | |
} | |
@Override | |
public Double accept(ExpressionVisitor visitor) { | |
return visitor.visit(this); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment