(******************************************************************) (* GENERATED FILE -- DO NOT EDIT -- GENERATED FILE -- DO NOT EDIT *) (* GENERATED FILE -- DO NOT EDIT -- GENERATED FILE -- DO NOT EDIT *) (* GENERATED FILE -- DO NOT EDIT -- GENERATED FILE -- DO NOT EDIT *) (******************************************************************)
signature LR_TABLE = sig datatype ('a,'b) pairlist = EMPTY | PAIR of'a * 'b * ('a,'b) pairlist datatype state = STATE of int datatype term = T of int datatype nonterm = NT of int datatype action = SHIFT of state
| REDUCE of int
| ACCEPT
| ERROR type table
val numStates : table -> int val numRules : table -> int val describeActions : table -> state ->
(term,action) pairlist * action val describeGoto : table -> state -> (nonterm,state) pairlist val action : table -> state * term -> action val goto : table -> state * nonterm -> state val initialState : table -> state
exception Goto of state * nonterm
(* TOKEN: signature revealing the internal structure of a token. This signature TOKENdistinctfromthesignature{parsername}_TOKENSproducedbyML-Yacc. The{parsername}_TOKENSstructurescontainsometypesandfunctionsto constructtokensfromvaluesandpositions.
(* LEXER: a signature that most lexers produced for use with SML-Yacc's outputwillmatch.Theuserisresponsiblefordeclaringtypetoken, typepos,andtypesvalueintheUserDeclarationssectionofalexer.
signature LEXER = sig structure UserDeclarations : sig type ('a,'b) token type pos type svalue end val makeLexer : (int -> string) -> unit ->
(UserDeclarations.svalue,UserDeclarations.pos) UserDeclarations.token end
(* ARG_LEXER: the %arg option of ML-Lex allows users to produce lexers which alsotakeanargumentbeforeyieldingafunctionfromunittoatoken
*)
signature ARG_LEXER = sig structure UserDeclarations : sig type ('a,'b) token type pos type svalue type arg end val makeLexer : (int -> string) -> UserDeclarations.arg -> unit ->
(UserDeclarations.svalue,UserDeclarations.pos) UserDeclarations.token end
(* PARSER_DATA: the signature of ParserData structures in {parser name}LrValsFun producedbySML-Yacc.Allsuchstructuresmatchthissignature.
signature PARSER_DATA = sig (* the type of line numbers *)
type pos
(* the type of semantic values *)
type svalue
(* the type of the user-supplied argument to the parser *) type arg
(* the intended type of the result of the parser. This value is producedbyapplyingextractfromthestructureActionstothe finalsemanticvalueresultiingfromaparse.
*)
(* structure Actions contains the functions which mantain the semanticvaluesstackintheparser.Voidisusedtoprovide adefaultvalueforthesemanticstack.
*)
structure Actions : sig val actions : int * pos *
(LrTable.state * (svalue * pos * pos)) list * arg->
LrTable.nonterm * (svalue * pos * pos) *
((LrTable.state *(svalue * pos * pos)) list) val void : svalue val extract : svalue -> result end
(* structure EC contains information used to improve error
recovery in an error-correcting parser *)
structure EC : sig val is_keyword : LrTable.term -> bool val noShift : LrTable.term -> bool val preferred_change : (LrTable.term list * LrTable.term list) list val errtermvalue : LrTable.term -> svalue val showTerminal : LrTable.term -> string val terms: LrTable.term list end
(* table is the LR table for the parser *)
val table : LrTable.table end
(* signature PARSER is the signature that most user parsers created by SML-Yaccwillmatch.
*)
type arg type lexarg type pos type result type svalue
val makeLexer : (int -> string) -> lexarg ->
(svalue,pos) Token.token Stream.stream val parse : int * ((svalue,pos) Token.token Stream.stream) *
(string * pos * pos -> unit) * arg ->
result * (svalue,pos) Token.token Stream.stream
val sameToken : (svalue,pos) Token.token * (svalue,pos) Token.token -> bool end
(**** Original file: join.sml ****)
(* ML-Yacc Parser Generator (c) 1989 Andrew W. Appel, David R. Tarditi *)
(* functor Join creates a user parser by putting together a Lexer structure, anLrValuesstructure,andapolymorphicparserstructure.Notethat theLexerandLrValuesstructuremustsharethetypepos(i.e.thetype oflinenumbers),thetypesvaluesforsemanticvalues,andthetype oftokens.
*)
type arg = ParserData.arg type pos = ParserData.pos type result = ParserData.result type svalue = ParserData.svalue val makeLexer = LrParser.Stream.streamify o Lex.makeLexer val parse = fn (lookahead,lexer,error,arg) =>
(fn (a,b) => (ParserData.Actions.extract a,b))
(LrParser.parse {table = ParserData.table,
lexer=lexer,
lookahead=lookahead,
saction = ParserData.Actions.actions,
arg=arg,
void= ParserData.Actions.void,
ec = {is_keyword = ParserData.EC.is_keyword,
noShift = ParserData.EC.noShift,
preferred_change = ParserData.EC.preferred_change,
errtermvalue = ParserData.EC.errtermvalue,
error=error,
showTerminal = ParserData.EC.showTerminal,
terms = ParserData.EC.terms}}
) val sameToken = Token.sameToken end
(* functor JoinWithArg creates a variant of the parser structure produced above.Inthiscase,themakeLexertakeanadditionalargumentbefore yieldingavalueoftypeunit->(svalue,pos)token
*)
type arg = ParserData.arg type lexarg = Lex.UserDeclarations.arg type pos = ParserData.pos type result = ParserData.result type svalue = ParserData.svalue
(* ML-Yacc Parser Generator (c) 1989 Andrew W. Appel, David R. Tarditi *) structure LrTable : LR_TABLE = struct open Array List
infix 9sub datatype ('a,'b) pairlist = EMPTY
| PAIR of'a * 'b * ('a,'b) pairlist datatype term = T of int datatype nonterm = NT of int datatype state = STATE of int datatype action = SHIFT of state
| REDUCE of int (* rulenum from grammar *)
| ACCEPT
| ERROR
exception Goto of state * nonterm type table = {states: int, rules : int,initialState: state,
action: ((term,action) pairlist * action) array,
goto : (nonterm,state) pairlist array} val numStates = fn ({states,...} : table) => states val numRules = fn ({rules,...} : table) => rules val describeActions =
fn ({action,...} : table) =>
fn (STATE s) => action sub s val describeGoto =
fn ({goto,...} : table) =>
fn (STATE s) => goto sub s fun findTerm (T term,row,default) = letfunfind (PAIR (T key,data,r)) = if key < term thenfind r elseif key=term then data else default
| find EMPTY = default infind row end fun findNonterm (NT nt,row) = letfunfind (PAIR (NT key,data,r)) = if key < nt thenfind r elseif key=nt then SOME data else NONE
| find EMPTY = NONE infind row end val action = fn ({action,...} : table) =>
fn (STATE state,term) => letval (row,default) = action sub state in findTerm(term,row,default) end val goto = fn ({goto,...} : table) =>
fn (a as (STATE state,nonterm)) => case findNonterm(nonterm,goto sub state) of SOME state => state
| NONE => raise (Goto a) val initialState = fn ({initialState,...} : table) => initialState val mkLrTable = fn {actions,gotos,initialState,numStates,numRules} =>
({action=actions,goto=gotos,
states=numStates,
rules=numRules,
initialState=initialState} : table) end;
(**** Original file: stream.sml ****)
(* ML-Yacc Parser Generator (c) 1989 Andrew W. Appel, David R. Tarditi *)
(* Stream: a structure implementing a lazy stream. The signature STREAM
is found in base.sig *)
structure Stream :> STREAM = struct datatype'a str = EVAL of 'a * 'a str Unsynchronized.ref | UNEVAL of (unit->'a)
type'a stream = 'a str Unsynchronized.ref
fun get(Unsynchronized.ref(EVAL t)) = t
| get(s as Unsynchronized.ref(UNEVAL f)) = letval t = (f(), Unsynchronized.ref(UNEVAL f)) in s := EVAL t; t end
fun streamify f = Unsynchronized.ref(UNEVAL f) fun cons(a,s) = Unsynchronized.ref(EVAL(a,s))
end;
(**** Original file: parser2.sml ****)
(* ML-Yacc Parser Generator (c) 1989 Andrew W. Appel, David R. Tarditi *)
(* parser.sml: This is a parser driver for LR tables with an error-recovery routineaddedtoit.Theroutineusedisdescribedindetailinthis article:
val DEBUG1 = false val DEBUG2 = false
exception ParseError
exception ParseImpossible of int
structure Fifo :> FIFO = struct type'a queue = ('a list * 'a list) val empty = (nil,nil)
exception Empty fun get(a::x, y) = (a, (x,y))
| get(nil, nil) = raise Empty
| get(nil, y) = get(rev y, nil) fun put(a,(x,y)) = (x,a::y) end
type ('a,'b) elem = (state * ('a * 'b * 'b)) type ('a,'b) stack = ('a,'b) elem list type ('a,'b) lexv = ('a,'b) token type ('a,'b) lexpair = ('a,'b) lexv * (('a,'b) lexv Stream.stream) type ('a,'b) distanceParse =
('a,'b) lexpair *
('a,'b) stack *
(('a,'b) stack * ('a,'b) lexpair) Fifo.queue *
int ->
('a,'b) lexpair *
('a,'b) stack *
(('a,'b) stack * ('a,'b) lexpair) Fifo.queue *
int *
action option
type ('a,'b) ecRecord =
{is_keyword : term -> bool,
preferred_change : (term list * term list) list,
error : string * 'b * 'b -> unit,
errtermvalue : term -> 'a,
terms : term list,
showTerminal : term -> string,
noShift : term -> bool}
local
val println = fn s => (TextIO.print s; TextIO.print"\n") val showState = fn (STATE s) => "STATE " ^ (Int.toString s) in fun printStack(stack: ('a,'b) stack, n: int) = case stack of (state,_) :: rest =>
(TextIO.print("\t" ^ Int.toString n ^ ": ");
println(showState state);
printStack(rest, n+1))
| nil => ()
fun prAction showTerminal
(stack as (state,_) :: _, next as (TOKEN (term,_),_), action) =
(println "Parse: state stack:";
printStack(stack, 0);
TextIO.print(" state="
^ showState state
^ " next="
^ showTerminal term
^ " action="
); case action of SHIFT state => println ("SHIFT " ^ (showState state))
| REDUCE i => println ("REDUCE " ^ (Int.toString i))
| ERROR => println "ERROR"
| ACCEPT => println "ACCEPT")
| prAction _ (_,_,action) = () end
(* ssParse: parser which maintains the queue of (state * lexvalues) in a steady-state.Ittakesatable,showTerminalfunction,saction function,andfixErrorfunction.ItparsesuntilanACCEPTis encountered,oranexceptionisraised.Whenanerrorisencountered, fixErroriscalledwiththeargumentsofparseStep(lexv,stack,and queue).Itreturnsthelexv,andanewstackandqueueadjustedso
that the lexv can be parsed *)
val ssParse =
fn (table,showTerminal,saction,fixError,arg) => letval prAction = prAction showTerminal val action = LrTable.action table val goto = LrTable.goto table fun parseStep(args as
(lexPair as (TOKEN (terminal, value as (_,leftPos,_)),
lexer
),
stack as (state,_) :: _,
queue)) = letval nextAction = action (state,terminal) val _ = if DEBUG1 then prAction(stack,lexPair,nextAction) else () incase nextAction of SHIFT s => letval newStack = (s,value) :: stack val newLexPair = Stream.get lexer val (_,newQueue) =Fifo.get(Fifo.put((newStack,newLexPair),
queue)) in parseStep(newLexPair,(s,value)::stack,newQueue) end
| REDUCE i =>
(case saction(i,leftPos,stack,arg) of (nonterm,value,stack as (state,_) :: _) =>
parseStep(lexPair,(goto(state,nonterm),value)::stack,
queue)
| _ => raise (ParseImpossible 197))
| ERROR => parseStep(fixError args)
| ACCEPT =>
(case stack of (_,(topvalue,_,_)) :: _ => letval (token,restLexer) = lexPair in (topvalue,Stream.cons(token,restLexer)) end
| _ => raise (ParseImpossible 202)) end
| parseStep _ = raise (ParseImpossible 204) in parseStep end
(* distanceParse: parse until n tokens are shifted, or accept or errorareencountered.Takesatable,showTerminalfunction,and semanticactionfunction.ReturnsaparserwhichtakesalexPair (lexresult*lexer),astatestack,aqueue,andadistance (mustbe>0)toparse.Theparserreturnsanewlex-value,astack withthenthtokenshiftedontop,aqueue,adistance,andaction
option. *)
val distanceParse =
fn (table,showTerminal,saction,arg) => letval prAction = prAction showTerminal val action = LrTable.action table val goto = LrTable.goto table fun parseStep(lexPair,stack,queue,0) = (lexPair,stack,queue,0,NONE)
| parseStep(lexPair as (TOKEN (terminal, value as (_,leftPos,_)),
lexer
),
stack as (state,_) :: _,
queue,distance) = letval nextAction = action(state,terminal) val _ = if DEBUG1 then prAction(stack,lexPair,nextAction) else () incase nextAction of SHIFT s => letval newStack = (s,value) :: stack val newLexPair = Stream.get lexer in parseStep(newLexPair,(s,value)::stack,
Fifo.put((newStack,newLexPair),queue),distance-1) end
| REDUCE i =>
(case saction(i,leftPos,stack,arg) of (nonterm,value,stack as (state,_) :: _) =>
parseStep(lexPair,(goto(state,nonterm),value)::stack,
queue,distance)
| _ => raise (ParseImpossible 240))
| ERROR => (lexPair,stack,queue,distance,SOME nextAction)
| ACCEPT => (lexPair,stack,queue,distance,SOME nextAction) end
| parseStep _ = raise (ParseImpossible 242) in parseStep : ('_a,'_b) distanceParse end
(* mkFixError: function to create fixError function which adjusts parser state
so that parse may continue in the presence of an error *)
(lexv as (TOKEN (term,value as (_,leftPos,_)),_),stack,queue) = letval _ = if DEBUG2 then
error("syntax error found at " ^ (showTerminal term),
leftPos,leftPos) else ()
fun tokAt(t,p) = TOKEN(t,(errtermvalue t,p,p))
val minDelta = 3
(* pull all the state * lexv elements from the queue *)
val stateList = letfun f q = letval (elem,newQueue) = Fifo.get q in elem :: (f newQueue) endhandle Fifo.Empty => nil in f queue end
(* now number elements of stateList, giving distance from
error token *)
val showTerms = String.concat o map (fn TOKEN(t,_) => " " ^ showTerminal t)
val printChange = fn c => letval CHANGE {distance,new,orig,pos,...} = c in (TextIO.print ("{distance= " ^ (Int.toString distance));
TextIO.print (",orig ="); TextIO.print(showTerms orig);
TextIO.print (",new ="); TextIO.print(showTerms new);
TextIO.print (",pos= " ^ (Int.toString pos));
TextIO.print"}\n") end
val printChangeList = app printChange
(* parse: given a lexPair, a stack, and the distance from the error
token, return the distance past the error token that we are able to parse.*)
fun parse (lexPair,stack,queuePos : int) = case distanceParse(lexPair,stack,Fifo.empty,queuePos+maxAdvance+1) of (_,_,_,distance,SOME ACCEPT) => if maxAdvance-distance-1 >= 0 then maxAdvance else maxAdvance-distance-1
| (_,_,_,distance,_) => maxAdvance - distance - 1
(* catList: concatenate results of scanning list *)
fun catList l f = List.foldr (fn(a,r)=> f a @ r) [] l
fun keywordsDelta new = ifList.exists (fn(TOKEN(t,_))=>is_keyword t) new then minDelta else0
fun tryChange{lex,stack,pos,leftPos,rightPos,orig,new} = letval lex' = List.foldr (fn (t',p)=>(t',Stream.cons p)) lex new val distance = parse(lex',stack,pos+length new-length orig) inif distance >= minAdvance + keywordsDelta new then [CHANGE{pos=pos,leftPos=leftPos,rightPos=rightPos,
distance=distance,orig=orig,new=new}] else [] end
(* tryDelete: Try to delete n terminals. Returnsingle-element[success]ornil.
Do not delete unshiftable terminals. *)
fun tryDelete n ((stack,lexPair as (TOKEN(term,(_,l,r)),_)),qPos) = letfun del(0,accum,left,right,lexPair) =
tryChange{lex=lexPair,stack=stack,
pos=qPos,leftPos=left,rightPos=right,
orig=rev accum, new=[]}
| del(n,accum,left,right,(tok as TOKEN(term,(_,_,r)),lexer)) = if noShift term then [] else del(n-1,tok::accum,left,r,Stream.get lexer) in del(n,[],l,r,lexPair) end
(* tryInsert: try to insert tokens before the current terminal;
return a list of the successes *)
fun tryInsert((stack,lexPair as (TOKEN(_,(_,l,_)),_)),queuePos) =
catList terms (fn t =>
tryChange{lex=lexPair,stack=stack,
pos=queuePos,orig=[],new=[tokAt(t,l)],
leftPos=l,rightPos=l})
(* trySubst: try to substitute tokens for the current terminal;
return a list of the successes *)
fun trySubst ((stack,lexPair as (orig as TOKEN (term,(_,l,r)),lexer)),
queuePos) = if noShift term then [] else
catList terms (fn t =>
tryChange{lex=Stream.get lexer,stack=stack,
pos=queuePos,
leftPos=l,rightPos=r,orig=[orig],
new=[tokAt(t,r)]})
(* do_delete(toks,lexPair) tries to delete tokens "toks" from "lexPair". Ifitsucceeds,returnsSOME(toks',l,r,lp),where toks'istheactualtokens(withpositionsandvalues)deleted, (l,r)arethe(leftmost,rightmost)positionoftoks', lpiswhatremainsofthestreamafterdeletion
*) fun do_delete(nil,lp as (TOKEN(_,(_,l,_)),_)) = SOME(nil,l,l,lp)
| do_delete([t],(tok as TOKEN(t',(_,l,r)),lp')) = if eqT (t, t') then SOME([tok],l,r,Stream.get lp') else NONE
| do_delete(t::rest,(tok as TOKEN(t',(_,l,r)),lp')) = if eqT (t,t') thencase do_delete(rest,Stream.get lp') of SOME(deleted,l',r',lp'') =>
SOME(tok::deleted,l,r',lp'')
| NONE => NONE else NONE
fun tryPreferred((stack,lexPair),queuePos) =
catList preferred_change (fn (delete,insert) => ifList.exists noShift delete then [] (* should give warning at
parser-generation time *) elsecase do_delete(delete,lexPair) of SOME(deleted,l,r,lp) =>
tryChange{lex=lp,stack=stack,pos=queuePos,
leftPos=l,rightPos=r,orig=deleted,
new=map (fn t=>(tokAt(t,r))) insert}
| NONE => [])
val findMaxDist = fn l => List.foldr (fn (CHANGE {distance,...},high) => Int.max(distance,high)) 0 l
(* maxDist: max distance past error taken that we could parse *)
val maxDist = findMaxDist changes
(* remove changes which did not parse maxDist tokens past the error token *)
val changes = catList changes
(fn(c as CHANGE{distance,...}) => if distance=maxDist then [c] else [])
incase changes of (l as change :: _) => letfun print_msg (CHANGE {new,orig,leftPos,rightPos,...}) = letval s = case (orig,new) of (_::_,[]) => "deleting " ^ (showTerms orig)
| ([],_::_) => "inserting " ^ (showTerms new)
| _ => "replacing " ^ (showTerms orig) ^ " with " ^ (showTerms new) in error ("syntax error: " ^ s,leftPos,rightPos) end
val _ =
(if length l > 1 andalso DEBUG2 then
(TextIO.print"multiple fixes possible; could fix it by:\n"; app print_msg l;
TextIO.print"chosen correction:\n") else ();
print_msg change)
(* findNth: find nth queue entry from the error entry.ReturnstheNthqueueentryandtheportionof thequeuefromthebeginningtothenth-1entry.The errorentryisattheendofthequeue.
Examples:
queue=abcde findNth0=(e,abcd) findNth1=(d,abc)
*)
val findNth = fn n => letfun f (h::t,0) = (h,rev t)
| f (h::t,n) = f(t,n-1)
| f (nil,_) = let exception FindNth inraise FindNth end in f (rev stateList,n) end
val CHANGE {pos,orig,new,...} = change val (last,queueFront) = findNth pos val (stack,lexPair) = last
val lp1 = List.foldl(fn (_,(_,r)) => Stream.get r) lexPair orig val lp2 = List.foldr(fn(t,r)=>(t,Stream.cons r)) lp1 new
val restQueue =
Fifo.put((stack,lp2), List.foldl Fifo.put Fifo.empty queueFront)
val (lexPair,stack,queue,_,_) =
distanceParse(lp2,stack,restQueue,pos)
in (lexPair,stack,queue) end
| nil => (error("syntax error found at " ^ (showTerminal term),
leftPos,leftPos); raise ParseError) end
val parse = fn {arg,table,lexer,saction,void,lookahead,
ec=ec as {showTerminal,...} : ('_a,'_b) ecRecord} => letval distance = 15(* defer distance tokens *) val minAdvance = 1(* must parse at least 1 token past error *) val maxAdvance = Int.max(lookahead,0)(* max distance for parse check *) val lexPair = Stream.get lexer val (TOKEN (_,(_,leftPos,_)),_) = lexPair val startStack = [(initialState table,(void,leftPos,leftPos))] val startQueue = Fifo.put((startStack,lexPair),Fifo.empty) val distanceParse = distanceParse(table,showTerminal,saction,arg) val fixError = mkFixError(ec,distanceParse,minAdvance,maxAdvance) val ssParse = ssParse(table,showTerminal,saction,fixError,arg) fun loop (lexPair,stack,queue,_,SOME ACCEPT) =
ssParse(lexPair,stack,queue)
| loop (lexPair,stack,queue,0,_) = ssParse(lexPair,stack,queue)
| loop (lexPair,stack,queue,distance,SOME ERROR) = letval (lexPair,stack,queue) = fixError(lexPair,stack,queue) in loop (distanceParse(lexPair,stack,queue,distance)) end
| loop _ = let exception ParseInternal inraise ParseInternal end in loop (distanceParse(lexPair,startStack,startQueue,distance)) end end;
;
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.