Skip to content

Commit

Permalink
Added Factor lexer.
Browse files Browse the repository at this point in the history
Thanks to John Benediktsson.
  • Loading branch information
orbitalquark committed Oct 20, 2024
1 parent c6c98d6 commit 0433791
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/lexerlist.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ used if [`fold.scintillua.by.indentation`][] is enabled. For SciTE, see *lexers/
1. Elm
1. Erlang`*`
1. F#
1. Factor
1. Fantom`*`
1. Faust
1. Fennel
Expand Down
1 change: 1 addition & 0 deletions docs/thanks.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ and better over the years.
* Ivan Baidakou
* Jason Schindler
* Jeff Stone
* John Benediktsson
* Jonathon Levi
* Joseph Eib
* Joshua Krämer
Expand Down
71 changes: 71 additions & 0 deletions lexers/factor.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
-- Copyright 2013 Michael T. Richter. See LICENSE.
-- Copyright 2024 John Benediktsson <mrjbq7@gmail.com>
-- Factor lexer (http://factorcode.org).

-- At this time the lexer is usable, but not perfect. Problems include:
-- * identifiers like (foo) get treated and coloured like stack declarations
-- * other as-yet unknown display bugs :-)

local lexer = lexer
local P, R, S = lpeg.P, lpeg.R, lpeg.S

local lex = lexer.new(...)

-- General building blocks.
local pre = lexer.upper^1
local post = pre
local opt_pre = pre^-1
local opt_post = opt_pre

-- Comments.
lex:add_rule('comment', lex:tag(lexer.COMMENT, P('#')^-1 * lexer.to_eol('!')))

-- Strings.
local dq1_str = opt_pre * lexer.range('"', true)
lex:add_rule('string', lex:tag(lexer.STRING, dq1_str))

-- Numbers.
-- Note that complex literals like C{ 1/3 27.3 } are not covered by this lexer.
-- The C{ ... } notation is treated as an operator--to be specific a
-- "constructor" (for want of a better term).
-- Also note that we cannot use lexer.number because numbers do not support the '+' prefix or
-- case-insensitive base-changing prefixes.
local hex_digits = lexer.xdigit^1
local binary = P('-')^-1 * '0b' * S('01')^1
local octal = P('-')^-1 * '0o' * R('07')^1
local decimal = P('-')^-1 * lexer.digit^1
local hexadecimal = P('-')^-1 * '0x' * hex_digits
local integer = binary + octal + hexadecimal + decimal
local ratio = decimal * '/' * decimal
local dfloat_component = decimal * '.' * decimal^-1
local hfloat_component = hexadecimal * ('.' * hex_digits^-1)^-1
local float = (dfloat_component * (S('eE') * decimal)^-1) + (hfloat_component * S('pP') * decimal) +
(ratio * '.') + (P('-')^-1 * '1/0.') + ('0/0')
lex:add_rule('number', lex:tag(lexer.NUMBER, (float + ratio + integer)))

-- Keywords.
-- Things like NAN:, USE:, USING:, POSTPONE:, etc. are considered keywords, as are similar
-- words that end in #.
-- Patterns like <<WORD ... WORD>> are similarly considered to be "keywords" (for want of a
-- better term).
local colon_words = pre * S(':#') + S(':;')^1
local angle_words = (P('<')^1 * post) + (pre * P('>')^1)
lex:add_rule('keyword', lex:tag(lexer.KEYWORD, (colon_words + angle_words)))

-- Operators.
-- The usual suspects like braces, brackets, angle brackets, parens, etc. are considered to be
-- operators. They may, however, have prefixes like C{ ... }.
local constructor_words = opt_pre * S('{[<') + S('}]>') + pre * '(' + ')'
local stack_declaration = lexer.range('(', ')')
local other_operators = S('+-*/<>')
lex:add_rule('operator',
lex:tag(lexer.OPERATOR, (stack_declaration + constructor_words + other_operators)))

-- Identifiers.
-- Identifiers can be practically anything but whitespace.
local symbols = S('`~!@#$%^&*()_-+={[<>]}:;X,?/')
lex:add_rule('identifier', lex:tag(lexer.IDENTIFIER, (lexer.alnum + symbols)^1))

lexer.property['factor.comment'] = '!'

return lex
1 change: 1 addition & 0 deletions lexers/lexer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,7 @@ function M.detect(filename, line)
elm = 'elm', --
erl = 'erlang', hrl = 'erlang', --
fs = 'fsharp', --
factor = 'factor', --
fan = 'fantom', --
dsp = 'faust', --
fnl = 'fennel', --
Expand Down
11 changes: 11 additions & 0 deletions scintillua.properties
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,17 @@ keywords6.$(file.patterns.fsharp)=scintillua
keywords7.$(file.patterns.fsharp)=scintillua
keywords8.$(file.patterns.fsharp)=scintillua
keywords9.$(file.patterns.fsharp)=scintillua
file.patterns.factor=*.factor
lexer.$(file.patterns.factor)=scintillua.factor
keywords.$(file.patterns.factor)=scintillua
keywords2.$(file.patterns.factor)=scintillua
keywords3.$(file.patterns.factor)=scintillua
keywords4.$(file.patterns.factor)=scintillua
keywords5.$(file.patterns.factor)=scintillua
keywords6.$(file.patterns.factor)=scintillua
keywords7.$(file.patterns.factor)=scintillua
keywords8.$(file.patterns.factor)=scintillua
keywords9.$(file.patterns.factor)=scintillua
file.patterns.fantom=*.fan
lexer.$(file.patterns.fantom)=scintillua.fantom
keywords.$(file.patterns.fantom)=scintillua
Expand Down
25 changes: 25 additions & 0 deletions tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,31 @@ function test_latex()
assert_fold_points(latex, code, folds)
end

-- Tests Factor lexer.
function test_factor()
local factor = lexer.load('factor')

local code = [[
#!/usr/bin/env factor
! comment
: foo ( a: integer b -- c )
{ 1.5 3/2 1234 1.2e3 } sum + "hello" length sqrt - ;
]]

local tags = {
COMMENT, '#!/usr/bin/env factor', --
COMMENT, '! comment', --
KEYWORD, ':', IDENTIFIER, 'foo', OPERATOR, '( a: integer b -- c )', --
OPERATOR, '{', NUMBER, '1.5', NUMBER, '3/2', NUMBER, '1234', NUMBER, '1.2e3', OPERATOR, '}', --
IDENTIFIER, 'sum', --
OPERATOR, '+', --
STRING, '\"hello\"', IDENTIFIER, 'length', IDENTIFIER, 'sqrt', --
OPERATOR, '-', --
KEYWORD, ';' --
}
assert_lex(factor, code, tags)
end

function test_legacy()
local lex = lexer.new('test')
local ws = lexer.token(lexer.WHITESPACE, lexer.space^1)
Expand Down

0 comments on commit 0433791

Please sign in to comment.