summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ccross.mlb5
-rw-r--r--ccross.sml5
-rw-r--r--common.sml2
-rw-r--r--driver.fun14
-rw-r--r--exn_handler.sml (renamed from exn_handler.fun)0
-rw-r--r--parser.fun348
-rw-r--r--parser.sig10
-rw-r--r--ppc.fun18
-rw-r--r--ppc.sig4
9 files changed, 397 insertions, 9 deletions
diff --git a/ccross.mlb b/ccross.mlb
index 38c8146..26be1c1 100644
--- a/ccross.mlb
+++ b/ccross.mlb
@@ -1,5 +1,6 @@
ann
"allowRecordPunExps true"
+ "allowOrPats true"
"warnUnused true"
in
$(SML_LIB)/basis/basis.mlb
@@ -11,7 +12,9 @@ in
tree.sig tree.sml
tokenizer.sig tokenizer.fun
ppc.sig ppc.fun
- exn_handler.sig exn_handler.fun
+ parser.sig parser.fun
+
+ exn_handler.sig exn_handler.sml
driver.sig driver.fun
ccross.sig ccross.sml
diff --git a/ccross.sml b/ccross.sml
index 7743b3b..92810b8 100644
--- a/ccross.sml
+++ b/ccross.sml
@@ -2,8 +2,9 @@ structure ccross:> CCROSS = struct
structure T:> TOKENIZER =
Tokenizer(structure H = Hashtable; structure S = Stream)
structure ppc:> PPC = ppc(structure Tree = Tree; structure T = T)
- structure D:> DRIVER = Driver(ppc)
- structure ExnHandler: EXN_HANDLER = ExnHandler
+ structure Parser:> PARSER = Parser(ppc)
+ structure D:> DRIVER = Driver(Parser)
+ structure ExnHandler:> EXN_HANDLER = ExnHandler
end
val () = MLton.Exn.setTopLevelHandler ccross.ExnHandler.handler
diff --git a/common.sml b/common.sml
index 5429a5f..02c3724 100644
--- a/common.sml
+++ b/common.sml
@@ -161,7 +161,7 @@ val I = fn z => bindWith2str Int.toString z
val C = fn z => bindWith2str str z
val B = fn z => bindWith2str Bool.toString z
val R = fn z => bind A1 (fn ((output, _), n) => app (fn f => f ())
- (List.tabulate (n, fn _ => fn () => output "\t"))) z
+ (List.tabulate (n, fn _ => fn () => output " "))) z
type ('t, 'a, 'b, 'c) a1printer = (bool * ((string -> unit) * 'a)) * 'b
-> 't -> ((bool * ((string -> unit) * 'a)) * 'b -> 'c) -> 'c
diff --git a/driver.fun b/driver.fun
index 5336987..3e2df5e 100644
--- a/driver.fun
+++ b/driver.fun
@@ -1,4 +1,4 @@
-functor Driver(P: PPC): DRIVER = struct
+functor Driver(P: PARSER): DRIVER = struct
structure P = P
datatype execMode = Normal | DebugE | DebugT
@@ -50,9 +50,15 @@ functor Driver(P: PPC): DRIVER = struct
val file = valOf $ #file config
in
case (#mode config) of
- Normal => die `"Normal mode is not implemented yet" %
- | DebugT => P.T.debugPrint file
- | DebugE => P.debugPrint file (#includeDirs config)
+ Normal =>
+ let
+ val parseCtx = P.createParseCtx file (#includeDirs config)
+ val (_, _) = P.parseDef parseCtx
+ in
+ raise Unimplemented
+ end
+ | DebugT => P.P.T.debugPrint file
+ | DebugE => P.P.debugPrint file (#includeDirs config)
end
end
diff --git a/exn_handler.fun b/exn_handler.sml
index c0a2d7a..c0a2d7a 100644
--- a/exn_handler.fun
+++ b/exn_handler.sml
diff --git a/parser.fun b/parser.fun
new file mode 100644
index 0000000..ccd467e
--- /dev/null
+++ b/parser.fun
@@ -0,0 +1,348 @@
+functor Parser(P: PPC): PARSER = struct
+
+ structure P = P
+ structure T = P.T
+
+ type parseCtx = P.t
+
+ datatype unop =
+ UnopPreInc |
+ UnopPreDec |
+ UnopAddr |
+ UnopDeref |
+ UnopPos |
+ UnopNeg |
+ UnopComp |
+ UnopLogNeg |
+
+ UnopPostInc |
+ UnopPostDec
+
+ datatype binop =
+ BinopMul |
+ BinopDiv |
+ BinopMod |
+ BinopSum |
+ BinopSub |
+ BinopShiftLeft |
+ BinopShiftRight |
+ BinopGreater |
+ BinopLess |
+ BinopLessEqual |
+ BinopGreaterEqual |
+ BinopEqual |
+ BinopNotEqual |
+ BinopBitAnd |
+ BinopBitXor |
+ BinopBitOr |
+ BinopLogAnd |
+ BinopLogOr |
+
+ BinopAssign |
+ BinopMulAssign |
+ BinopDivAssign |
+ BinopModAssign |
+ BinopSumAssign |
+ BinopSubAssign |
+ BinopLeftShiftAssign |
+ BinopRightShiftAssign |
+ BinopBitAndAssign |
+ BinopBitXorAssign |
+ BinopBitOrAssign
+
+ val binopTable = [
+ (BinopMul, T.Asterisk, 13, true),
+ (BinopDiv, T.Slash, 13, true),
+ (BinopMod, T.Percent, 13, true),
+ (BinopSum, T.Plus, 12, true),
+ (BinopSub, T.Minus, 12, true),
+ (BinopShiftLeft, T.DoubleLess, 11, true),
+ (BinopShiftRight, T.DoubleGreater, 11, true),
+ (BinopGreater, T.Greater, 10, true),
+ (BinopLess, T.Less, 10, true),
+ (BinopLessEqual, T.LessEqualSign, 10, true),
+ (BinopGreaterEqual, T.GreaterEqualSign, 10, true),
+ (BinopEqual, T.DoubleEqualSign, 9, true),
+ (BinopNotEqual, T.ExclMarkEqualSign, 9, true),
+ (BinopBitAnd, T.Ampersand, 8, true),
+ (BinopBitXor, T.Cap, 7, true),
+ (BinopBitOr, T.VerticalBar, 6, true),
+ (BinopLogAnd, T.DoubleAmpersand, 5, true),
+ (BinopLogOr, T.DoubleVerticalBar, 4, true),
+
+ (BinopAssign, T.EqualSign, 3, false),
+ (BinopMulAssign, T.AmpersandEqualSign, 3, false),
+ (BinopDivAssign, T.SlashEqualSign, 3, false),
+ (BinopModAssign, T.PercentEqualSign, 3, false),
+ (BinopSumAssign, T.PlusEqualSign, 3, false),
+ (BinopSubAssign, T.MinusEqualSign, 3, false),
+ (BinopLeftShiftAssign, T.DoubleLessEqualSign, 3, false),
+ (BinopRightShiftAssign, T.DoubleGreaterEqualSign, 3, false),
+ (BinopBitAndAssign, T.AmpersandEqualSign, 3, false),
+ (BinopBitXorAssign, T.CapEqualSign, 3, false),
+ (BinopBitOrAssign, T.VerticalBarEqualSign, 3, false)
+ ]
+
+ datatype expr =
+ Enum |
+ Eid of string |
+ Estrlit of string |
+ EmemberByV of string * exprAug |
+ EmemberByP of string * exprAug |
+ Eunop of unop * exprAug |
+ Ebinop of binop * exprAug * exprAug
+
+ and exprAug = EAug of expr * P.tkPos
+
+ datatype exprPart =
+ EPexpr of exprAug |
+ (* last two are prio and leftAssoc *)
+ EPbinop of binop * P.tkPos * int * bool
+
+ type def = expr
+
+ datatype token =
+ Tk of T.token |
+ TkParens of (token * P.tkPos) list |
+ TkBrackets of (token * P.tkPos) list |
+ TkBraces of (token * P.tkPos) list
+
+ fun createParseCtx fname incDirs =
+ P.create { fname, incDirs, debugMode = false }
+
+ fun getToken ppc =
+ let
+ val (tk, pos, ppc) = P.getToken ppc
+ in
+ case tk of
+ T.LParen | T.LBracket | T.LBrace => raise Unimplemented
+ | _ => (Tk tk, pos, ppc)
+ end
+
+ val Punop = fn z =>
+ let
+ fun Punop (out, unop) =
+ Printf out `(case unop of
+ UnopPreInc | UnopPostInc => "++"
+ | UnopPreDec | UnopPostDec => "--"
+ | UnopPos => "+"
+ | UnopNeg => "-"
+ | UnopAddr => "&"
+ | UnopDeref => "*"
+ | UnopComp => "~"
+ | UnopLogNeg => "!") %
+ in
+ bind A1 Punop
+ end z
+
+ val Pbinop = fn z =>
+ let
+ fun Pbinop (out, binop) =
+ case List.find (fn (binop', _, _, _) => binop' = binop) binopTable
+ of
+ SOME (_, tk, _, _) => Printf out T.Ptk tk%
+ | NONE => raise Unreachable
+ in
+ bind A1 Pbinop
+ end z
+
+ fun printExpr off ea =
+ let
+ fun printExpr' off (EAug (e, pos)) =
+ let
+ fun Pprintf g = printf R off (fn (a, _) =>
+ g (a, fn (_, out) => Printf out `"| " P.PtkPos pos %))
+
+ fun member (member, ea) s = (
+ Pprintf `"(" `s `member %;
+ printf `"\n" %;
+ printExpr' (off + 1) ea;
+ printf `")" %
+ )
+ in
+ case e of
+ Eid id => Pprintf `id %
+ | Enum => Pprintf `"num" %
+ | Estrlit s => Pprintf `"\"" `s `"\"" %
+ | EmemberByV pair => member pair "."
+ | EmemberByP pair => member pair "->"
+ | Eunop (unop, ea) => (
+ Pprintf `"(" Punop unop %;
+ printf `"\n" %;
+ printExpr' (off + 1) ea;
+ printf `")" %
+ )
+ | Ebinop (binop, left, right) => (
+ Pprintf `"(" Pbinop binop %;
+ printf `"\n" %;
+ printExpr (off + 1) left;
+ printExpr' (off + 1) right;
+ printf `")" %
+ )
+ end
+ in
+ printExpr' off ea;
+ printf `"\n" %
+ end
+
+ fun parseUnaryPrefix ppc acc =
+ let
+ val unopPreTable = [
+ (T.DoublePlus, UnopPreInc),
+ (T.DoubleMinus, UnopPreDec),
+ (T.Plus, UnopPos),
+ (T.Minus, UnopNeg)
+ ]
+ val (tk, pos, ppc') = getToken ppc
+ in
+ case tk of
+ Tk tk => (
+ case List.find (fn (tk', _) => tk' = tk) unopPreTable of
+ SOME (_, unop) => parseUnaryPrefix ppc' ((unop, pos) :: acc)
+ | _ => (acc, ppc)
+ )
+ | _ => (acc, ppc)
+ end
+
+ fun parsePrimaryExpr ppc =
+ let
+ val (tk, pos, ppc) = getToken ppc
+ in
+ (fn e => (EAug (e, pos), ppc))
+ (case tk of
+ Tk (T.Id id) => Eid id
+ | Tk (T.StringConst s) => Estrlit s
+ | Tk (T.CharConst _) => raise Unimplemented
+ | Tk (T.Num _) => Enum
+ | _ => P.clerror pos [P.Cid, P.Cconst])
+ end
+
+ fun parseExprSuffix1 eAug ppc =
+ let
+ val (tk, pos1, ppc1) = getToken ppc
+
+ fun formUnop1 unop = (SOME (EAug (Eunop (unop, eAug), pos1)), ppc1)
+ fun formMemberOp unop =
+ let
+ val (tk, pos2, ppc2) = getToken ppc1
+ in
+ case tk of
+ Tk (T.Id id) => (SOME (EAug (unop (id, eAug), pos1)), ppc2)
+ | _ => P.clerror pos2 [P.Cid]
+ end
+ in
+ case tk of
+ Tk T.DoublePlus => formUnop1 UnopPostInc
+ | Tk T.DoubleMinus => formUnop1 UnopPostDec
+ | Tk T.Dot => formMemberOp EmemberByV
+ | Tk T.Arrow => formMemberOp EmemberByP
+ | _ => (NONE, ppc)
+ end
+
+ fun parseExprSuffix eAug ppc =
+ let
+ val (eAug', ppc) = parseExprSuffix1 eAug ppc
+ in
+ case eAug' of
+ SOME eAug => parseExprSuffix eAug ppc
+ | NONE => (eAug, ppc)
+ end
+
+ fun parseUnary ppc =
+ let
+ val (prefix, ppc) = parseUnaryPrefix ppc []
+ val (eAug, ppc) = parsePrimaryExpr ppc
+ val (eAug, ppc) = parseExprSuffix eAug ppc
+
+ val eAug = List.foldl
+ (fn ((unop, pos), e) => EAug (Eunop (unop, e), pos)) eAug prefix
+ in
+ (EPexpr eAug, ppc)
+ end
+
+ fun parseBinop ppc =
+ let
+ val (tk, pos, ppc) = getToken ppc
+ in
+ case tk of
+ Tk tk => (
+ case List.find (fn (_, tk', _, _) => tk' = tk) binopTable of
+ SOME (binop, _, prio, leftAssoc) =>
+ SOME (EPbinop (binop, pos, prio, leftAssoc), ppc)
+ | NONE =>
+ if tk = T.EOS then
+ NONE
+ else
+ P.clerror pos [P.Cbinop]
+ )
+ | _ => P.clerror pos [P.Cbinop]
+ end
+
+ fun constructExpr parts =
+ let
+ fun shouldTakePrev _ [] = false
+ | shouldTakePrev (_, _, p, assoc) ((_, _, p') :: _) =
+ case Int.compare (p', p) of
+ GREATER => true
+ | EQUAL => assoc
+ | LESS => false
+
+ fun moveHead vstack opstack =
+ let
+ fun take2 (x :: y :: tl) = (x, y, tl)
+ | take2 _ = raise Unreachable
+ val (right, left, vstack) = take2 vstack
+ val (binop', pos, _) = hd opstack
+
+ val head = EAug (Ebinop (binop', left, right), pos)
+ in
+ (head :: vstack, tl opstack)
+ end
+
+ fun insert (Q as (binop, pos, p, _)) (vstack, opstack) =
+ if shouldTakePrev Q opstack then
+ insert Q (moveHead vstack opstack)
+ else
+ (vstack, (binop, pos, p) :: opstack)
+
+ fun finish ([ea], []) = ea
+ | finish (_, []) = raise Unreachable
+ | finish (vstack, opstack) = finish $ moveHead vstack opstack
+
+ fun construct (vstack, opstack) (EPexpr ea :: acc) =
+ construct (ea :: vstack, opstack) acc
+ | construct stacks (EPbinop Q :: acc) =
+ construct (insert Q stacks) acc
+ | construct stacks [] = finish stacks
+ in
+ construct ([], []) parts
+ end
+
+ fun parseExpr ppc =
+ let
+ fun collect ppc expVal acc =
+ if expVal then
+ let
+ val (unary, ppc) = parseUnary ppc
+ in
+ collect ppc (not expVal) (unary :: acc)
+ end
+ else
+ case parseBinop ppc of
+ SOME (binop, ppc) => collect ppc (not expVal) (binop :: acc)
+ | NONE => (rev acc, ppc)
+
+ val (parts, ppc) = collect ppc true []
+ val expr = constructExpr parts
+ in
+ (expr, ppc)
+ end
+
+ fun parseDef ppc =
+ let
+ val (expr, ppc) = parseExpr ppc
+ val () = printExpr 0 expr
+ in
+ (raise Unimplemented, ppc)
+ end
+end
diff --git a/parser.sig b/parser.sig
new file mode 100644
index 0000000..7545f22
--- /dev/null
+++ b/parser.sig
@@ -0,0 +1,10 @@
+signature PARSER = sig
+
+ structure P: PPC
+
+ type parseCtx
+ type def
+
+ val createParseCtx: string -> string list -> parseCtx
+ val parseDef: parseCtx -> def * parseCtx
+end
diff --git a/ppc.fun b/ppc.fun
index bb07107..6f4e8b2 100644
--- a/ppc.fun
+++ b/ppc.fun
@@ -147,6 +147,22 @@ struct
prefix
end
+ val PtkPos = fn z =>
+ let
+ fun PtkPos (out, TkPos (p as T.S.Pos (fname, line, col), layers)) =
+ case layers of
+ [] => Printf out T.S.Ppos p %
+ | _ =>
+ let
+ val prefix = PlayersCompact (out, SOME fname, layers)
+ val fname = String.extract (fname, size prefix, NONE)
+ in
+ Printf out `"; @" T.S.Ppos (T.S.Pos (fname, line, col)) %
+ end
+ in
+ bind A1 PtkPos
+ end z
+
val startCache = (0, [], ("", 0))
fun printTokenCompact (off, layers, (fname, line)) out (tk, pos) =
@@ -961,7 +977,7 @@ struct
updatePpc P u#buffer (updateH head) %
end
- and getTokenSkipNL ppc =
+ fun getTokenSkipNL ppc =
let
val (tk, pos, ppc) = getToken ppc
in
diff --git a/ppc.sig b/ppc.sig
index ce7a720..b2dcbae 100644
--- a/ppc.sig
+++ b/ppc.sig
@@ -13,7 +13,11 @@ signature PPC = sig
Cbinop |
Cop
+ val clerror: tkPos -> tkClass list -> 'a
+
val create: { fname: string, incDirs: string list, debugMode: bool } -> t
val getToken: t -> T.token * tkPos * t
val debugPrint: string -> string list -> unit
+
+ val PtkPos: (tkPos, 'a, 'b, 'c) a1printer
end