lama_byterun/stdlib/Matcher.lama

109 lines
2.5 KiB
Text

-- (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) {
[regexp (r), name]
}
-- 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) {
local i, l = line, c = col;
for i := pos, i < 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) {
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) {
local n;
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)
}