mp.lua (4867B)
1 local M = {_NAME = "mp"} 2 3 local l = require("lexer") 4 local P, R, S = lpeg.P, lpeg.R, lpeg.S 5 local T = l.token 6 local any = P(1) 7 local dec = R"09" 8 local alpha = R("AZ", "az") 9 local hws = S"\t " 10 local vws = S"\n\r" 11 local ws = hws + vws 12 local function I(s) -- Case-insensitive string match 13 local p = P(true) 14 for i = 1, #s do 15 local c = s:sub(i, i) 16 p = p * (P(c:lower()) + P(c:upper())) 17 end 18 return p 19 end 20 local function N(p, min, max) 21 max = max or min 22 return p^min - p^(max+1) 23 end 24 25 local whitespace = T("whitespace", ws^1) 26 27 local comment_keyword = T("comment_keyword", I"todo" + I"xxx" + I"fixme") 28 local comment_text = T("comment_text", (any - P"\n" - comment_keyword)^1) 29 local comment = T("comment_text", P"%") * (comment_text + comment_keyword)^0 * T("whitespace", P"\n") 30 31 local numlit = T("numlit", (dec^0 * P".")^-1 * dec^1) 32 33 local strlit = T("strlit", P"\"" * (any - vws - S"\"")^0 * P"\"") 34 35 local delimiter = T("delimiter", S"()[]{};,") 36 37 local operator = T("operator", S"<=>:+-*/.&|" + l.word_match{ 38 "thru", "atleast", "of", "cycle", "on", "off", 39 "makepen", "makepath", "penoffset", 40 "char", "substring", 41 42 -- Number operators 43 "angle", "dir", "sind", "sin", "asin", "cosd", "cos", "acos", "tand", "tan", "atan", 44 "floor", "ceiling", "round", "abs", "length", "normalize", "sqrt", "mod", "div", "dotprod", 45 "mexp", "mlog", 46 "normaldeviate", "uniformdeviate", 47 48 -- Boolean opereators 49 "not", "and", "or", "even", "odd", "known", "unknown", 50 "isnumber", "ispair", "ispath", "istransform", "isrgbcolor", "iscolor", "iscmykcolor", "isstring", "isboolean", "ispicture", "ispen", "cyclic", 51 52 -- Transformations 53 "transformed", "rotated", "slanted", "reflectedabout", "shifted", "xshifted", "yshifted", "scaled", "xscaled", "yscaled", "zscaled", "rotatedaround", "rotatedabout", 54 "inverse", 55 56 -- BBox operators 57 "ulcorner", "llcorner", "urcorner", "lrcorner", "center", "bbox", 58 "width", "height", "ascent", "descent", 59 60 -- Path operators 61 "arclength", "arctime", "direction", "directiontime", "directionpoint", "intersectiontimes", "intersectionpoint", "point", "precontrol", "postcontrol", "reverse", "subpath", "subcycle", "cutbefore", "cutafter", "cutcycle", "tensepath", 62 "envelope", "turningnumber", "cw", "ccw", 63 64 -- Pair operators 65 "xpart", "ypart", "xxpart", "xypart", "yxpart", "yypart", "swap", 66 "cyanpart", "magentapart", "yellowpart", "blackpart", 67 "redpart", "greenpart", "bluepart", 68 "greypart", "dashpart", "fontpart", "pathpart", "penpart", "textpart", 69 70 -- Draw options 71 "dashed", "withpen", "withprescript", "withpostscript", "withoutcolor", "withrgbcolor", "withcolor", "withcmykcolor", "withgreyscale", 72 }) 73 74 local suffix = T("suffix", P"#@" + P"@#" + P"@") 75 76 local keyword = T("keyword", l.word_match{ 77 "input", "endinput", "end", "dump", "shipout", "special", 78 "begingroup", "endgroup", 79 "scantokens", "expandafter", "ea", 80 "let", "def", "vardef", "primarydef", "secondarydef", "tertiarydef", "enddef", 81 "outer", "inner", "save", "interim", "delimiters", 82 "show", "showdependencies", "showtoken", "showvariable", "showstats", 83 "errhelp", "errmessage", "message", 84 "batchmode", "nonstopmode", "scrollmode", "errorstopmode", 85 "addto", "also", "contour", "doublepath", "clip", "setbounds", 86 "controls", "tension", "curl", 87 "if", "elseif", "else", "fi", "exitif", "exitunless", 88 "for", "forsuffixes", "forever", "step", "until", "upto", "downto", "endfor", 89 }) 90 91 local constant = T("constant", l.word_match{ 92 "mitered", "rounded", "beveled", "butt", "squared", 93 94 -- Number 95 "eps", "epsilon", "inf", 96 97 -- Pair 98 "left", "right", "up", "down", "origin", 99 100 -- Path 101 "circle", "square", 102 103 -- Transform 104 "id", 105 106 -- String 107 "dquote", "EOF", 108 109 -- Boolean 110 "true", "false", 111 112 -- Picture 113 "nullpicture", 114 115 -- Pen 116 "nullpen", "pencircle", "pensquare", "penrazor", "penspeck", 117 }) 118 119 local type_ = T("type", l.word_match{ 120 "newinternal", 121 122 -- Builtin types 123 "numeric", "pair", "path", "transform", "rgbcolor", "color", 124 "cmykcolor", "string", "boolean", "picture", "pen", 125 126 -- Parameters 127 "text", "expr", "suffix", "primary", "secondary", "tertiary", 128 129 -- r3mp aliases 130 "internal", "number", 131 }) 132 133 local identifier = T("identifier", (alpha + P"_")^1) 134 135 M._rules = { 136 {"whitespace", whitespace}, 137 {"comment", comment}, 138 {"numlit", numlit}, 139 {"strlit", strlit}, 140 {"delimiter", delimiter}, 141 {"operator", operator}, 142 {"suffix", suffix}, 143 {"keyword", keyword}, 144 {"constant", constant}, 145 {"type", type_}, 146 {"identifier", identifier}, 147 } 148 149 M._tokenstyles = { 150 whitespace = l.STYLE_WHITESPACE, 151 152 comment_text = l.STYLE_COMMENT, 153 comment_keyword = l.STYLE_COMMENT_KEYWORD, 154 155 numlit = l.STYLE_NUMBER, 156 157 strlit = l.STYLE_STRING, 158 159 delimiter = l.STYLE_DELIMITER, 160 operator = l.STYLE_OPERATOR, 161 suffix = l.STYLE_LABEL, -- TODO: this makes no sense 162 163 keyword = l.STYLE_KEYWORD, 164 constant = l.STYLE_CONSTANT, 165 ["type"] = l.STYLE_TYPE, 166 identifier = l.STYLE_IDENTIFIER, 167 } 168 169 return M