wenzelm@29315: (* Title: Pure/Thy/thy_syntax.ML wenzelm@23726: Author: Makarius wenzelm@23726: wenzelm@29315: Superficial theory syntax: tokens and spans. wenzelm@23726: *) wenzelm@23726: wenzelm@29315: signature THY_SYNTAX = wenzelm@23726: sig wenzelm@27842: val token_source: Scan.lexicon * Scan.lexicon -> Position.T -> (string, 'a) Source.source -> wenzelm@30573: (OuterLex.token, (Symbol_Pos.T, Position.T * (Symbol.symbol, (string, 'a) wenzelm@27770: Source.source) Source.source) Source.source) Source.source wenzelm@27842: val parse_tokens: Scan.lexicon * Scan.lexicon -> Position.T -> string -> OuterLex.token list wenzelm@23803: val present_token: OuterLex.token -> output wenzelm@27842: val report_token: OuterLex.token -> unit wenzelm@27842: datatype span_kind = Command of string | Ignored | Malformed wenzelm@27842: type span wenzelm@27842: val span_kind: span -> span_kind wenzelm@27842: val span_content: span -> OuterLex.token list wenzelm@27665: val span_range: span -> Position.range wenzelm@27842: val span_source: (OuterLex.token, 'a) Source.source -> wenzelm@27842: (span, (OuterLex.token, 'a) Source.source) Source.source wenzelm@27842: val parse_spans: Scan.lexicon * Scan.lexicon -> Position.T -> string -> span list wenzelm@27665: val present_span: span -> output wenzelm@27842: val report_span: span -> unit wenzelm@28434: val unit_source: (span, 'a) Source.source -> wenzelm@28438: (span * span list * bool, (span, 'a) Source.source) Source.source wenzelm@23726: end; wenzelm@23726: wenzelm@29315: structure ThySyntax: THY_SYNTAX = wenzelm@23726: struct wenzelm@23726: wenzelm@28434: structure K = OuterKeyword; wenzelm@23726: structure T = OuterLex; wenzelm@23726: structure P = OuterParse; wenzelm@23726: wenzelm@23726: wenzelm@23803: (** tokens **) wenzelm@23803: wenzelm@23803: (* parse *) wenzelm@23726: wenzelm@27842: fun token_source lexs pos src = wenzelm@27842: Symbol.source {do_recover = true} src wenzelm@27842: |> T.source {do_recover = SOME false} (K lexs) pos; wenzelm@23726: wenzelm@27842: fun parse_tokens lexs pos str = wenzelm@27842: Source.of_string str wenzelm@27842: |> token_source lexs pos wenzelm@27842: |> Source.exhaust; wenzelm@23726: wenzelm@23726: wenzelm@23803: (* present *) wenzelm@23726: wenzelm@23726: local wenzelm@23726: wenzelm@23726: val token_kind_markup = wenzelm@27846: fn T.Command => (Markup.commandN, []) wenzelm@27846: | T.Keyword => (Markup.keywordN, []) wenzelm@27846: | T.Ident => Markup.ident wenzelm@27846: | T.LongIdent => Markup.ident wenzelm@27846: | T.SymIdent => Markup.ident wenzelm@29319: | T.Var => Markup.var wenzelm@29319: | T.TypeIdent => Markup.tfree wenzelm@29319: | T.TypeVar => Markup.tvar wenzelm@27846: | T.Nat => Markup.ident wenzelm@27846: | T.String => Markup.string wenzelm@27846: | T.AltString => Markup.altstring wenzelm@27846: | T.Verbatim => Markup.verbatim wenzelm@27846: | T.Space => Markup.none wenzelm@27846: | T.Comment => Markup.comment wenzelm@27846: | T.InternalValue => Markup.none wenzelm@27846: | T.Malformed => Markup.malformed wenzelm@27846: | T.Error _ => Markup.malformed wenzelm@27846: | T.Sync => Markup.control wenzelm@27846: | T.EOF => Markup.control; wenzelm@23726: wenzelm@23803: in wenzelm@23803: wenzelm@23726: fun present_token tok = wenzelm@23726: Markup.enclose (token_kind_markup (T.kind_of tok)) (Output.output (T.unparse tok)); wenzelm@23726: wenzelm@27842: fun report_token tok = wenzelm@27842: Position.report (token_kind_markup (T.kind_of tok)) (T.position_of tok); wenzelm@27842: wenzelm@23803: end; wenzelm@23803: wenzelm@23803: wenzelm@23803: wenzelm@27665: (** spans **) wenzelm@27665: wenzelm@27842: (* type span *) wenzelm@27842: wenzelm@27842: datatype span_kind = Command of string | Ignored | Malformed; wenzelm@27842: datatype span = Span of span_kind * OuterLex.token list; wenzelm@23803: wenzelm@27842: fun span_kind (Span (k, _)) = k; wenzelm@27842: fun span_content (Span (_, toks)) = toks; wenzelm@27842: wenzelm@27842: fun span_range span = wenzelm@27842: (case span_content span of wenzelm@27842: [] => (Position.none, Position.none) wenzelm@27842: | toks => wenzelm@27665: let wenzelm@27665: val start_pos = T.position_of (hd toks); wenzelm@27756: val end_pos = T.end_position_of (List.last toks); wenzelm@27842: in (start_pos, end_pos) end); wenzelm@23803: wenzelm@23803: wenzelm@23803: (* parse *) wenzelm@23726: wenzelm@23803: local wenzelm@23803: wenzelm@27665: val is_whitespace = T.is_kind T.Space orf T.is_kind T.Comment; wenzelm@27665: wenzelm@27665: val body = Scan.unless (Scan.many is_whitespace -- Scan.ahead (P.command || P.eof)) P.not_eof; wenzelm@23726: wenzelm@27665: val span = wenzelm@27665: Scan.ahead P.command -- P.not_eof -- Scan.repeat body wenzelm@27842: >> (fn ((name, c), bs) => Span (Command name, c :: bs)) || wenzelm@27842: Scan.many1 is_whitespace >> (fn toks => Span (Ignored, toks)) || wenzelm@27842: Scan.repeat1 body >> (fn toks => Span (Malformed, toks)); wenzelm@23726: wenzelm@23726: in wenzelm@23726: wenzelm@27842: fun span_source src = Source.source T.stopper (Scan.bulk span) NONE src; wenzelm@23803: wenzelm@23803: end; wenzelm@23803: wenzelm@27842: fun parse_spans lexs pos str = wenzelm@27842: Source.of_string str wenzelm@27842: |> token_source lexs pos wenzelm@27842: |> span_source wenzelm@27842: |> Source.exhaust; wenzelm@23803: wenzelm@23803: wenzelm@23803: (* present *) wenzelm@23803: wenzelm@23803: local wenzelm@23803: wenzelm@27665: fun kind_markup (Command name) = Markup.command_span name wenzelm@27665: | kind_markup Ignored = Markup.ignored_span wenzelm@27842: | kind_markup Malformed = Markup.malformed_span; wenzelm@23803: wenzelm@23803: in wenzelm@23803: wenzelm@27842: fun present_span span = wenzelm@27842: Markup.enclose (kind_markup (span_kind span)) (implode (map present_token (span_content span))); wenzelm@27842: wenzelm@27842: fun report_span span = wenzelm@27842: Position.report (kind_markup (span_kind span)) (Position.encode_range (span_range span)); wenzelm@23803: wenzelm@23803: end; wenzelm@23803: wenzelm@28434: wenzelm@28434: wenzelm@28434: (** units: commands with proof **) wenzelm@28434: wenzelm@28434: (* scanning spans *) wenzelm@28434: wenzelm@28434: val eof = Span (Command "", []); wenzelm@28434: wenzelm@28434: fun is_eof (Span (Command "", _)) = true wenzelm@28434: | is_eof _ = false; wenzelm@28434: wenzelm@28434: val not_eof = not o is_eof; wenzelm@28434: wenzelm@28434: val stopper = Scan.stopper (K eof) is_eof; wenzelm@28434: wenzelm@28434: wenzelm@28434: (* unit_source *) wenzelm@28434: wenzelm@28434: local wenzelm@28434: wenzelm@28434: fun command_with pred = Scan.one (fn (Span (Command name, _)) => pred name | _ => false); wenzelm@28434: wenzelm@28434: val proof = Scan.pass 1 (Scan.repeat (Scan.depend (fn d => wenzelm@28454: if d <= 0 then Scan.fail wenzelm@28434: else wenzelm@28454: command_with K.is_qed_global >> pair ~1 || wenzelm@28434: command_with K.is_proof_goal >> pair (d + 1) || wenzelm@28454: (if d = 0 then Scan.fail else command_with K.is_qed >> pair (d - 1)) || wenzelm@28438: Scan.unless (command_with K.is_theory) (Scan.one not_eof) >> pair d)) -- Scan.state); wenzelm@28434: wenzelm@28438: val unit = wenzelm@28454: command_with K.is_theory_goal -- proof >> (fn (a, (bs, d)) => (a, bs, d >= 0)) || wenzelm@28438: Scan.one not_eof >> (fn a => (a, [], true)); wenzelm@28434: wenzelm@28434: in wenzelm@28434: wenzelm@28434: fun unit_source src = Source.source stopper (Scan.bulk unit) NONE src; wenzelm@28434: wenzelm@23726: end; wenzelm@28434: wenzelm@28434: end;