-- (C) Dmitry Boulytchev, St. Petersburg State University, JetBrains Research, 2020 -- Matcher: simple string matching library. -- Create a regular expression representation. -- Arguments: -- r --- a string representation for regular expression (as per GNU regexp) -- name --- a string describing the meaning of the expression in free form -- (e.g. "identifier", "string constant", etc.), used for error -- reporting public fun createRegexp (r, name) { var l = [regexp (r), name]; l } -- Create an immutable matcher. -- Arguments: -- buf --- a string to match in -- pos --- an integer beginning position to match from -- line, col --- line and column numbers -- This function is internal, do not use it directly. -- To initially create a matcher use initMatcher function (see below). fun createMatcher (buf, pos, line, col) { -- Shows a matcher in a readable form fun show () { sprintf ("buf : %-40s\npos : %d\nline: %d\ncol : %d\n", buf, pos, line, col) } -- Calculates the number of remaining unmatched characters in the buffer fun rest () { buf.length - pos } -- Moves the position pointer on given number of characters. fun shift (n) { var i, l = line, c = col; for i := pos, i < pos+n, i := i+1 do case buf [i] of '\n' -> l := l + 1; c := 1 | '\t' -> c := c + 8 | _ -> c := c + 1 esac od; createMatcher (buf, pos + n, l, c) } fun matchString (s) { fun min (x, y) { if x < y then x else y fi } -- printf ("Matching string %s against %s...\n", s, substring (buf, pos, min (10, buf.length - pos))); if s.length > rest () then Fail (sprintf ("""%s"" expected", s), line, col) elif matchSubString (buf, s, pos) then Succ (s, shift (s.length)) else Fail (sprintf ("""%s"" expected at", s), line, col) fi } fun matchRegexp (r) { var n; fun min (x, y) { if x < y then x else y fi } -- printf ("Matching regexp %x against %s...\n", r, substring (buf, pos, min (10, buf.length - pos))); if (n := regexpMatch (r[0], buf, pos)) >= 0 then Succ (substring (buf, pos, n), shift (n)) else Fail (sprintf ("%s expected", r[1]), line, col) fi } fun eof () { if rest () == 0 then Succ ("", shift (0)) else Fail ("EOF expected", line, col) fi } [show, eof, matchString, matchRegexp, fun () {line}, fun () {col}] } public fun showMatcher (m) { m [0] () } public fun endOfMatcher (m) { m [1] () } public fun matchString (m, s) { m [2] (s) } -- Matches against a regexp public fun matchRegexp (m, r) { m [3] (r) } -- Gets a line number public fun getLine (m) { m [4] () } -- Gets a column number public fun getCol (m) { m [5] () } -- Creates a fresh matcher from a string buffer public fun initMatcher (buf) { createMatcher (buf, 0, 1, 1) }