Skip to content

Commit

Permalink
Add Forth lexer
Browse files Browse the repository at this point in the history
  • Loading branch information
tkers committed Oct 15, 2022
1 parent f5b0382 commit 22dcaf5
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/Languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
- Erlang (`erlang`)
- Escape (`escape`)
- Factor (`factor`)
- Forth (`forth`)
- Fortran (`fortran`)
- FreeFEM (`freefem`)
- FSharp (`fsharp`)
Expand Down
5 changes: 5 additions & 0 deletions lib/rouge/demos/forth
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
: greet ( c-addr u -- )
10 20 at-xy
." Hello" type cr ;

s" World" greet bye
5 changes: 5 additions & 0 deletions lib/rouge/guessers/disambiguation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ def match?(filename)

Puppet
end

disambiguate '*.fs' do
next Forth if matches?(/:\s+.+?\s+\(\s+--\s+\)/)
next FSharp
end
end
end
end
93 changes: 93 additions & 0 deletions lib/rouge/lexers/forth.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
module Lexers
class Forth < RegexLexer
title "Forth"
desc "The Forth programming language"
tag 'forth'
aliases 'fs'
filenames '*.fs', '*.fth', '*.4th'
mimetypes 'text/x-forth'

def self.detect?(text)
return true if text.shebang? 'gforth'
end

def self.keywords
@keywords ||= Set.new %w(
:NONAME ; DOES> [ ] ]L IMMEDIATE
DO ?DO LOOP +LOOP
BEGIN UNTIL AGAIN REPEAT WHILE
IF ELSE THEN
CASE ENDCASE OF ENDOF
LITERAL RECURSE
['] [COMPILE] POSTPONE
TO IS
' CHAR
)
end

state :root do
rule %r/\s+/m, Text::Whitespace

# comments
rule %r/\\\s+.*$/, Comment::Single
rule %r/#!\s+.*$/, Comment::Hashbang
rule %r/\(\s+/, Comment::Multiline, :comment_paren

# strings
rule %r/(s"|c"|."|abort")/i, Str::Double, :string_quote
rule %r/(\.\()/i, Str::Double, :string_paren

# single character
rule %r/(\[char\])(\s+)(\S)/i do
groups Keyword, Text, Str::Char
end

# numbers
rule %r/\-?\$\h+(?=\s)/, Num::Hex
rule %r/\-?%[01]+(?=\s)/, Num::Bin
rule %r/\-?#?\d+(?=\s)/, Num

# constants
rule %r/(true|false|bl|cell)(?=\s)/i, Keyword::Constant

# includes
rule %r/(require|include)(\s+)(\S+)/i do
groups Keyword::Namespace, Text::Whitespace, Str
end

# definitions
rule %r/(:|create|variable|constant|value|defer)(\s+)(\S+)/i do
groups Keyword::Declaration, Text::Whitespace, Name::Function
end

# keywords
rule %r/\S+/ do |m|
if self.class.keywords.include?(m[0].upcase)
token Keyword
else
token Name
end
end
end

state :comment_paren do
rule %r([^\)]+), Comment::Multiline
rule %r(\)), Comment::Multiline, :pop!
end

state :string_quote do
rule %r/[^\"]+/, Str::Double
rule %r/"/, Str::Double, :pop!
end

state :string_paren do
rule %r/[^\)]+/, Str::Double
rule %r/\)/, Str::Double, :pop!
end
end
end
end
24 changes: 24 additions & 0 deletions spec/lexers/forth_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*- #
# frozen_string_literal: true

describe Rouge::Lexers::Forth do
let(:subject) { Rouge::Lexers::Forth.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.fs', :source => ': noop ( -- ) ;'
assert_guess :filename => 'foo.fth'
assert_guess :filename => 'foo.4th'
end

it 'guesses by mimetype' do
assert_guess :mimetype => 'text/x-forth'
end

it 'guesses by source' do
assert_guess :source => '#! /usr/bin/gforth'
end
end
end
2 changes: 1 addition & 1 deletion spec/lexers/fsharp_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.fs'
assert_guess :filename => 'foo.fs', :source => 'let foo = bar()'
assert_guess :filename => 'foo.fsx'
end

Expand Down
32 changes: 32 additions & 0 deletions spec/visual/samples/forth
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
\ Sample Forth program

REQUIRE compat.fs

: square ( n -- n ) DUP * ;

10 CONSTANT pad-size
CREATE extra-pad pad-size square CELLS ALLOT
VARIABLE color $ec627a color !
DEFER main

: ix>weekday ( u -- c-addr u )
CASE
0 OF s" Sunday" ENDOF
1 OF s" Monday" ENDOF
2 OF s" Tuesday" ENDOF
3 OF s" Wednesday" ENDOF
4 OF s" Thursday" ENDOF
5 OF s" Friday" ENDOF
6 OF s" Saturday" ENDOF
ENDCASE ;

: .weekdays ( -- )
7 0 ?DO
[CHAR] - EMIT SPACE
I ix>weekday TYPE CR
[ 10 square ]L MS
LOOP ;

:noname ( -- )
." Hello World!"
.weekdays BYE ; IS main

0 comments on commit 22dcaf5

Please sign in to comment.