diff options
author | Matth?us G. Chajdas <dev@anteru.net> | 2019-11-10 13:56:53 +0100 |
---|---|---|
committer | Matth?us G. Chajdas <dev@anteru.net> | 2019-11-10 13:56:53 +0100 |
commit | 1dd3124a9770e11b6684e5dd1e6bc15a0aa3bc67 (patch) | |
tree | 87a171383266dd1f64196589af081bc2f8e497c3 /tests/examplefiles/example.whiley | |
parent | f1c080e184dc1bbc36eaa7cd729ff3a499de568a (diff) | |
download | pygments-master.tar.gz |
Diffstat (limited to 'tests/examplefiles/example.whiley')
-rw-r--r-- | tests/examplefiles/example.whiley | 296 |
1 files changed, 0 insertions, 296 deletions
diff --git a/tests/examplefiles/example.whiley b/tests/examplefiles/example.whiley deleted file mode 100644 index 74b39370..00000000 --- a/tests/examplefiles/example.whiley +++ /dev/null @@ -1,296 +0,0 @@ -/** - * Example Whiley program, taken from the Whiley benchmark suite. - * https://github.com/Whiley/WyBench/blob/master/src/101_interpreter/Main.whiley - */ - -import whiley.lang.System -import whiley.lang.Int -import whiley.io.File -import string from whiley.lang.ASCII -import char from whiley.lang.ASCII - -// ==================================================== -// A simple calculator for expressions -// ==================================================== - -constant ADD is 0 -constant SUB is 1 -constant MUL is 2 -constant DIV is 3 - -// binary operation -type BOp is (int x) where ADD <= x && x <= DIV -type BinOp is { BOp op, Expr lhs, Expr rhs } - -// variables -type Var is { string id } - -// list access -type ListAccess is { - Expr src, - Expr index -} - -// expression tree -type Expr is int | // constant - Var | // variable - BinOp | // binary operator - Expr[] | // array constructor - ListAccess // list access - -// values -type Value is int | Value[] - -// stmts -type Print is { Expr rhs } -type Set is { string lhs, Expr rhs } -type Stmt is Print | Set - -// ==================================================== -// Expression Evaluator -// ==================================================== - -type RuntimeError is { string msg } -type Environment is [{string k, Value v}] - -// Evaluate an expression in a given environment reducing either to a -// value, or a runtime error. The latter occurs if evaluation gets -// "stuck" (e.g. expression is // not well-formed) -function evaluate(Expr e, Environment env) -> Value | RuntimeError: - // - if e is int: - return e - else if e is Var: - return env[e.id] - else if e is BinOp: - Value|RuntimeError lhs = evaluate(e.lhs, env) - Value|RuntimeError rhs = evaluate(e.rhs, env) - // check if stuck - if !(lhs is int && rhs is int): - return {msg: "arithmetic attempted on non-numeric value"} - // switch statement would be good - if e.op == ADD: - return lhs + rhs - else if e.op == SUB: - return lhs - rhs - else if e.op == MUL: - return lhs * rhs - else if rhs != 0: - return lhs / rhs - return {msg: "divide-by-zero"} - else if e is Expr[]: - [Value] r = [] - for i in e: - Value|RuntimeError v = evaluate(i, env) - if v is RuntimeError: - return v - else: - r = r ++ [v] - return r - else if e is ListAccess: - Value|RuntimeError src = evaluate(e.src, env) - Value|RuntimeError index = evaluate(e.index, env) - // santity checks - if src is [Value] && index is int && index >= 0 && index < |src|: - return src[index] - else: - return {msg: "invalid list access"} - else: - return 0 // dead-code - -// ==================================================== -// Expression Parser -// ==================================================== - -type State is { string input, int pos } -type SyntaxError is { string msg, int start, int end } - -function SyntaxError(string msg, int start, int end) -> SyntaxError: - return { msg: msg, start: start, end: end } - -// Top-level parse method -function parse(State st) -> (Stmt,State)|SyntaxError: - // - Var keyword, Var v - Expr e - int start = st.pos - // - keyword,st = parseIdentifier(st) - switch keyword.id: - case "print": - any r = parseAddSubExpr(st) - if !(r is SyntaxError): - e,st = r - return {rhs: e},st - else: - return r // error case - case "set": - st = parseWhiteSpace(st) - v,st = parseIdentifier(st) - any r = parseAddSubExpr(st) - if !(r is SyntaxError): - e,st = r - return {lhs: v.id, rhs: e},st - else: - return r // error case - default: - return SyntaxError("unknown statement",start,st.pos-1) - -function parseAddSubExpr(State st) -> (Expr, State)|SyntaxError: - // - Expr lhs, Expr rhs - // First, pass left-hand side - any r = parseMulDivExpr(st) - // - if r is SyntaxError: - return r - // - lhs,st = r - st = parseWhiteSpace(st) - // Second, see if there is a right-hand side - if st.pos < |st.input| && st.input[st.pos] == '+': - // add expression - st.pos = st.pos + 1 - r = parseAddSubExpr(st) - if !(r is SyntaxError): - rhs,st = r - return {op: ADD, lhs: lhs, rhs: rhs},st - else: - return r - else if st.pos < |st.input| && st.input[st.pos] == '-': - // subtract expression - st.pos = st.pos + 1 - r = parseAddSubExpr(st) - if !(r is SyntaxError): - rhs,st = r - return {op: SUB, lhs: lhs, rhs: rhs},st - else: - return r - // No right-hand side - return (lhs,st) - -function parseMulDivExpr(State st) -> (Expr, State)|SyntaxError: - // First, parse left-hand side - Expr lhs, Expr rhs - any r = parseTerm(st) - if r is SyntaxError: - return r - // - lhs,st = r - st = parseWhiteSpace(st) - // Second, see if there is a right-hand side - if st.pos < |st.input| && st.input[st.pos] == '*': - // add expression - st.pos = st.pos + 1 - r = parseMulDivExpr(st) - if !(r is SyntaxError): - rhs,st = r - return {op: MUL, lhs: lhs, rhs: rhs}, st - else: - return r - else if st.pos < |st.input| && st.input[st.pos] == '/': - // subtract expression - st.pos = st.pos + 1 - r = parseMulDivExpr(st) - if !(r is SyntaxError): - rhs,st = r - return {op: DIV, lhs: lhs, rhs: rhs}, st - else: - return r - // No right-hand side - return (lhs,st) - -function parseTerm(State st) -> (Expr, State)|SyntaxError: - // - st = parseWhiteSpace(st) - if st.pos < |st.input|: - if ASCII.isLetter(st.input[st.pos]): - return parseIdentifier(st) - else if ASCII.isDigit(st.input[st.pos]): - return parseNumber(st) - else if st.input[st.pos] == '[': - return parseList(st) - // - return SyntaxError("expecting number or variable",st.pos,st.pos) - -function parseIdentifier(State st) -> (Var, State): - // - string txt = "" - // inch forward until end of identifier reached - while st.pos < |st.input| && ASCII.isLetter(st.input[st.pos]): - txt = txt ++ [st.input[st.pos]] - st.pos = st.pos + 1 - return ({id:txt}, st) - -function parseNumber(State st) -> (Expr, State)|SyntaxError: - // inch forward until end of identifier reached - int start = st.pos - while st.pos < |st.input| && ASCII.isDigit(st.input[st.pos]): - st.pos = st.pos + 1 - // - int|null iv = Int.parse(st.input[start..st.pos]) - if iv == null: - return SyntaxError("Error parsing number",start,st.pos) - else: - return iv, st - -function parseList(State st) -> (Expr, State)|SyntaxError: - // - st.pos = st.pos + 1 // skip '[' - st = parseWhiteSpace(st) - [Expr] l = [] // initial list - bool firstTime = true - while st.pos < |st.input| && st.input[st.pos] != ']': - if !firstTime && st.input[st.pos] != ',': - return SyntaxError("expecting comma",st.pos,st.pos) - else if !firstTime: - st.pos = st.pos + 1 // skip ',' - firstTime = false - any r = parseAddSubExpr(st) - if r is SyntaxError: - return r - else: - Expr e - e,st = r - // perform annoying error check - l = l ++ [e] - st = parseWhiteSpace(st) - st.pos = st.pos + 1 - return l,st - -// Parse all whitespace upto end-of-file -function parseWhiteSpace(State st) -> State: - while st.pos < |st.input| && ASCII.isWhiteSpace(st.input[st.pos]): - st.pos = st.pos + 1 - return st - -// ==================================================== -// Main Method -// ==================================================== - -public method main(System.Console sys): - if(|sys.args| == 0): - sys.out.println("no parameter provided!") - else: - File.Reader file = File.Reader(sys.args[0]) - string input = ASCII.fromBytes(file.readAll()) - - Environment env = Environment() - State st = {pos: 0, input: input} - while st.pos < |st.input|: - Stmt s - any r = parse(st) - if r is SyntaxError: - sys.out.println("syntax error: " ++ r.msg) - return - s,st = r - Value|RuntimeError v = evaluate(s.rhs,env) - if v is RuntimeError: - sys.out.println("runtime error: " ++ v.msg) - return - if s is Set: - env[s.lhs] = v - else: - sys.out.println(r) - st = parseWhiteSpace(st) - |