[ create a new paste ] login | about

Link: http://codepad.org/1RREka9a    [ raw code | fork ]

Corsix - Lua, pasted on Aug 14:
local lpeg = require "lpeg"
assert(tonumber(lpeg.version()) >= 0.9, "LPEG version >= 0.9 is required")

local function set(t)
  local s = {}
  for i, v in ipairs(t) do
    s[v] = true
  end
  return s
end

local C, P, R, S, V = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V
local Carg, Cc, Cp, Ct = lpeg.Carg, lpeg.Cc, lpeg.Cp, lpeg.Ct

local tokens_C = P { "tokens";

  -- Comment of form /* ... */
  comment = Ct(C(P"/*" * (V"newline" + (1 - P"*/"))^0 * P"*/") * Cc"comment"),
  
  -- Single line comment
  line_comment = Ct(C(P"//" * (1 - V"newline")^0)  * Cc"comment_line"),
  
  -- Single platform independant line break which increments line number
  newline = (P"\r\n" + P"\n\r" + S"\r\n") * (Cp() * Carg(1)) / function(pos, state)
    state.line = state.line + 1
    state.line_start = pos
  end,
  
  -- Line continuation
  line_extend = Ct(C(P[[\]] * V"newline") * Cc"line_extend"),
  
  -- Whitespace of any length (includes newlines)
  whitespace = Ct(C((S" \t" + V"newline")^1) * Cc"whitespace"),
  
  -- Special form of #include with filename followed in angled brackets (matches 3 tokens)
  include = Ct(C(P"#include") * Cc"preprocessor") *
            Ct(C(S" \t"^1) * Cc"whitespace") *
            Ct(C(P"<" * (1 - P">")^1 * P">") * Cc"string"),

  -- Preprocessor instruction
  preprocessor = V"include" +
                 Ct(C(P"#" * ( P"define" + P"elif" + P"else" + P"endif" +
                               P"error" + P"ifdef" + P"ifndef" + P"if" + P"import" +
                               P"include" + P"line" + P"pragma" + P"undef" + P"using"
                             ) * #S" \r\n\t") * Cc"preprocessor"),

  -- Identifier of form [a-zA-Z_][a-zA-Z0-9_]*
  identifier = Ct(C(R("az","AZ","__") * R("09","az","AZ","__")^0) * Cc"identifier"),
  
  -- Single character in a string
  string_char = R("az","AZ","09") + S"$%^&*()_-+={[}]:;@~#<,>.?/ \t" + (P"\\" * S[[ntvbrfa\?'"0]]),
  
  -- String literal
  string = Ct(C(P"'" * (V"string_char" + P'"')^0 * P"'" +
                P'"' * (V"string_char" + P"'")^0 * P'"') * Cc"string"),
  
  -- Operator
  operator = Ct(C(P">>=" + P"<<=" + P"..." +
                  P"::" + P"<<" + P">>" + P"<=" + P">=" + P"==" + P"!=" +
                  P"||" + P"&&" + P"++" + P"--" + P"->" + P"+=" + P"-=" +
                  P"*=" + P"/=" + P"|=" + P"&=" + P"^=" + S"+-*/=<>%^|&.?:!~,") * Cc"operator"),

  -- Misc. char (token type is the character itself)
  char = Ct(C(S"[]{}();") / function(x) return x, x end),
  
  -- Hex, octal or decimal number
  int = Ct(C((P"0x" * R("09","af","AF")^1) + (P"0" * R"07"^0) + R"09"^1) * Cc"integer"),
  
  -- Floating point number
  f_exponent = S"eE" + S"+-"^-1 * R"09"^1,
  f_terminator = S"fFlL",
  float = Ct(C(
            R"09"^1 * V"f_exponent" * V"f_terminator"^-1 +
            R"09"^0 * P"." * R"09"^1 * V"f_exponent"^-1 * V"f_terminator"^-1 +
            R"09"^1 * P"." * R"09"^0 * V"f_exponent"^-1 * V"f_terminator"^-1
          ) * Cc"float"),


  -- Any token
  token = V"comment" +
          V"line_comment" +
          V"identifier" +
          V"whitespace" +
          V"line_extend" +
          V"preprocessor" +
          V"string" +
          V"char" +
          V"operator" +
          V"float" + 
          V"int",
  
  -- Error for when nothing else matches
  error = (Cp() * C(P(1) ^ -8) * Carg(1)) / function(pos, where, state)
    error(("Tokenising error on line %i, position %i, near '%s'")
      :format(state.line, pos - state.line_start + 1, where))
  end,
  
  -- Match end of input or throw error
  finish = -P(1) + V"error",
  
  -- Match stream of tokens into a table
  tokens = Ct(V"token" ^ 0) * V"finish",
}

function TokeniseC(str)
  return tokens_C:match(str, 1, {line = 1, line_start = 1})
end

local escape_replacements = {
  ["<"] = "&lt;",
  [">"] = "&gt;",
  ["&"] = "&amp;",
}
local function escape(str)
  return str:gsub("[<>&]", escape_replacements)
end
local function token_span(class)
  return function(tok)
    return '<span class="'.. class ..'">'.. escape(tok[1]) ..'</span>'
  end
end

local C_keywords = set {
  "break", "case", "char", "const", "continue", "default", "do", "double",
  "else", "enum", "extern", "float", "for", "goto", "if", "int", "long",
  "register", "return", "short", "signed", "sizeof", "static", "struct",
  "switch", "typedef", "union", "unsigned", "void", "volatile", "while",
  "class", "public", "protected", "private", "template", "operator",
}
local C_to_HTML_handlers = {
  comment = token_span"c",
  comment_line = token_span"c",
  identifier = function(tok)
    if C_keywords[tok[1]] then
      return '<span class="k k_' .. tok[1] .. '">' .. tok[1] .. '</span>'
    else
      return '<span class="i">' .. escape(tok[1]) .. '</span>'
    end
  end,
  preprocessor = token_span"p",
  string = token_span"s",
}

function C_to_HTML(str)
  local tokens = TokeniseC(str)
  local result = {}
  for i, token in ipairs(tokens) do
    local handler = C_to_HTML_handlers[token[2]]
    if handler then
      token = handler(token)
    else
      token = escape(token[1])
    end
    result[#result + 1] = token
  end
  return '<pre class="C">'.. table.concat(result) ..'</pre>'
end

print [[<style type="text/css">
pre.C {
  background-color: #EBEBEB;
}

pre.C span.p, code.C span.p { /* preprocessor */
  color: #00F;
}

pre.C span.k, code.C span.k { /* keywords */
  color: #00F;
}

pre.C span.c, code.C span.c { /* comments */
  color: #008000;
}

pre.C span.s, code.C span.s { /* strings */
  color: #A31515;
} </style>]]

print(C_to_HTML[[class call {
    int nargs;
public:
    lua_State *L;

    call(lua_State *_L, const char *name)
        : L(_L),nargs(0)  {
        lua_getfield(L, LUA_GLOBALSINDEX, name);
    }

    call& incr_args()  {
        ++nargs;
        return *this;
    }

    void docall()    {
        if (lua_pcall(L,nargs,LUA_MULTRET,0) != 0) {
            cerr << (char*)lua_tostring(L,-1) << endl;
        }
    }
    
    // other
    static int something(lua_State *L) {
      lua_pushliteral(L, "Hello World");
    }
};

]])


Create a new paste based on this one


Comments: