Created
September 19, 2012 01:49
-
-
Save island205/3747156 to your computer and use it in GitHub Desktop.
lexer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Lexer | |
| @EOF:-1 | |
| @EOF_TYPE:1 | |
| p:0 | |
| c:"" | |
| constructor:(@input)-> | |
| @c = @input[@p] | |
| ### | |
| get next char | |
| ### | |
| consume:-> | |
| @p++ | |
| if @p >= @input.length | |
| @c = Lexer.EOF | |
| else | |
| @c = @input[@p] | |
| match:(x)-> | |
| if @c = x | |
| @consume() | |
| else | |
| throw new Error | |
| nextToken:-> | |
| getTokenName:(tokenType)-> | |
| class Parser | |
| lookahead:null | |
| constructor:(@input)-> | |
| @consume() | |
| match:(x)-> | |
| if @lookahead.type is x | |
| @consume() | |
| else | |
| throw new Error "expecting lookahead" | |
| consume:-> | |
| @lookahead = @input.nextToken() | |
| class Token | |
| constructor:(@type, @text)-> | |
| toString:-> | |
| tname = ListLexer.tokenNames[@type] | |
| "<#{@type},#{@text}>" | |
| class ListLexer extends Lexer | |
| @NAME:2 | |
| @COMMA:3 | |
| @LBRACK:4 | |
| @RBRACK:5 | |
| @tokenNames:["n/a", "<EOF>", "NAME", "COMMA", "LBRACK", "RBRACK"] | |
| getTokenName:(x)-> | |
| @tokenNames[x] | |
| isLETTER:()-> | |
| @c>='a' && @c<='z' || @c>='A' && @c<='Z' | |
| nextToken:()-> | |
| ### | |
| if char is not EOF | |
| ### | |
| while @c isnt Lexer.EOF | |
| switch @c | |
| #eat all blank | |
| when " ","\t","\n","\r" | |
| @WS() | |
| #if char is COMMA return a COMMA token | |
| when ',' | |
| @consume() | |
| return new Token ListLexer.COMMA,',' | |
| when '[' | |
| @consume() | |
| return new Token ListLexer.LBRACK,'[' | |
| when ']' | |
| @consume() | |
| return new Token ListLexer.RBRACK,']' | |
| else | |
| #if char is a LETTER get the name | |
| if @isLETTER() | |
| return @NAME() | |
| throw new Error('nextToken') | |
| return new Token ListLexer.EOF_TYPE,"<EOF>" | |
| NAME:-> | |
| buf = [] | |
| while @isLETTER() | |
| buf.push @c | |
| @consume() | |
| new Token ListLexer.NAME, buf.join() | |
| WS:-> | |
| while @c==' ' || @c=='\t' || @c=='\n' || @c=='\r' | |
| @consume() | |
| class ListParser extends Parser | |
| list:-> | |
| @match ListLexer.LBRACK | |
| @elements() | |
| @match ListLexer.RBRACK | |
| elements:()-> | |
| @element() | |
| while @lookahead.type is ListLexer.COMMA | |
| @match ListLexer.COMMA | |
| @element() | |
| return | |
| element:-> | |
| if @lookahead.type is ListLexer.NAME | |
| @match ListLexer.NAME | |
| else if @lookahead.type is ListLexer.LBRACK | |
| @list() | |
| else | |
| throw new Error() | |
| ### | |
| lexer = new ListLexer "[a, b]" | |
| t = lexer.nextToken() | |
| while t.type isnt Lexer.EOF_TYPE | |
| console.log t | |
| t = lexer.nextToken() | |
| console.log t | |
| ### | |
| lexer = new ListLexer "[[a, [a, b], b]]" | |
| parser = new ListParser lexer | |
| parser.list() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
这是解释器么?