-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
解析器 #2
Comments
另外还有 虽然 duangsuse 太菜甚至连递归都不熟,没有获得真知的标志,也勉强可以套用别人的模式左递归完成语法 Lite 运算符优先级别:
|
d56dd9d 写了个现在还很有问题的 parser |
体积不过关,已打回 虽然我的确可以完全分开 parser 和执行引擎 |
http://www2.cs.tum.edu/projects/cup/ 世界上最好的 parserc 世界上最好的 scanner generator |
语法新约 |
由于 duangsuse 喜爱(虽然质量差)但行数极多的代码 直接在原项目上修改 重写的事情以后再说 新语义特性必须实现 |
本来可以更简洁,因为 duangsuse 喜欢行数多的项目(我一定会改的)... 这次先不删除其实可以去掉的重复代码,而且还会添加更多多余的代码
|
算了我还是重写吧... 这次文本处理部分使用 JFlex 和 cup https://github.com/jflex-de/jflex/tree/master/jflex/examples/java |
另外字符串内联表达式(冰封说官方名称叫 string interpolation)这种东西怎么能少呢 我还是支持
这种语法糖,这种特殊的 string 在解析时创建,取值时内联表达式被求值 |
https://github.com/duangsuse/Lite/blob/master/pretty_new/parser.cup RT, cup 的语法实在是不简洁的让人乍舌,我决定暂时没有这个「内建 Parser」了 |
垃圾 duangsuse, 解析器的问题有什么好说的,累了就不要做那么复杂,你看我现在都又被他们关了起来 😿 |
大不了让他们选择要不要加上 100k 左右去使用解析器来执行代码文本
|
而执行引擎就更好了,大部分应用不需要执行代码文本,所以只是更好的选择而已(不过以后做 IDEA 插件某些事情还是逃不掉的)(至少要改现在的 JFlex 词法啊)(VSCode 还好) 而如果一定要费那么大力气去让 JFlex 能理解 Lite 的某些特殊词法(或者是在我那 800 行代码上无聊代码上修改),然后让 Cup 去匹配,不累死我了 现在我也的确是不想再在解释器上花更多时间了,后面还有 GeekApk,5 天内完成这上面的工作必须的 |
(乱用 issue management 系列) 不过和自己对比的确进步了一些(从项目大小来看... 虽然我觉得水平没啥变化) 因为 GeekApk 是一定不能再拖下去的,只好以后再学,不过资料都有 |
Lite/Lime 和隔壁的 CovScript 和 Lice 一比虽然语法上有一些特色,终究代码不行 比较: class Lexer(sourceCode: String) {
private val sourceCode = sourceCode.toCharArray()
private var line = 1
private var col: Int
private var charIndex: Int
private var tokenBuffer: MutableList<Token> = ArrayList(50)
private var currentTokenIndex: Int = 0
init {
this.col = 1
this.charIndex = 0
doSplitTokens()
}
fun currentToken() = // assert(currentTokenIndex < this.tokenBuffer.size)
this.tokenBuffer[this.currentTokenIndex]
fun peekOneToken() = // assert(currentTokenIndex + 1 < this.tokenBuffer.size)
this.tokenBuffer[this.currentTokenIndex + 1]
fun nextToken() = this.currentTokenIndex++
private fun doSplitTokens() {
while (currentChar() != '\u0000') {
when {
currentChar() == '-' -> disambiguateIdentifierOrNegative()
currentChar() in decDigits -> lexNumber()
currentChar() in firstIdChars -> lexIdentifier()
currentChar() in lispSymbols -> lexSingleCharToken()
currentChar() == '"' -> lexString()
currentChar() == ';' -> skipComment()
currentChar() in blanks -> nextChar()
else -> throw ParseException("Unknown character ${currentChar()}", MetaData(this.line, this.line, this.col, this.col + 1))
}
}
tokenBuffer.add(Token(Token.TokenType.EOI, "", this.line, this.line, this.col, this.col + 1))
this.currentTokenIndex = 0
}
private fun disambiguateIdentifierOrNegative() {
if (peekOneChar() in decDigits) lexNumber()
else lexIdentifier()
}
private fun lexIdentifier() {
val line = this.line
val startAtCol = this.col
val str = scanFullString(idChars)
this.tokenBuffer.add(Token(Token.TokenType.Identifier, str, this.line, this.line, startAtCol, this.col))
}
private fun lexNumber() {
val line = this.line
val startAtCol = this.col
var isNegative = false
var numberType: Token.TokenType
var numberStr: String
if (currentChar() == '-') {
isNegative = true
package lite.lexer;
import java.util.ArrayList;
import java.util.Scanner;
/**
* The Lite Lexer
*
* @author duangsuse
* @see lite.Parser
* @since 1.0
*/
public class Lexer {
/**
* Code string
*/
public String code;
/**
* Parsing line
*/
public int line;
/**
* Parsing at column
*/
public int column;
/**
* Parsing char index
*/
public int c;
/**
* Current character
*/
public char curC;
/**
* Result tokens
*/
public ArrayList<Token> tokens = new ArrayList<>();
/**
* Lexer state
* 0 = null
* 1 = ignoring comment, expecting newline/eof
* 2 = building string
* 3 = building single-quoted string
* 4 = logging number
* 5 = logging identifier
* 66 = error when lexing
*/
public byte lexerState;
/**
* Verbose lex
*/
public boolean verbose = false;
/**
* Error string
*/
public String error;
/**
* Where the string starts
*/
public int stringStarting;
/**
* Temp String builder
*/
public StringBuilder temp = new StringBuilder();
/**
* Split : in identifier (true)
*/
public boolean splitComma = true;
/**
* Blank constructor
*/
public Lexer() {
}
/**
* Lite code lexer constructor
*
* @param lite lite code to lex
*/
public Lexer(String lite) {
code = lite;
line = 0;
column = 0;
c = 0;
lexerState = 0;
}
/**
* Reads file from stdIn, output tokens to stdout
*
* @param args commandline arguments
*/
public static void main(String[] args) {
boolean verbose = false;
boolean listOutput = true;
boolean deflate = false;
for (String s : args) {
if (s.equals("-v")) {
verbose = true;
}
if (s.equals("-p")) {
listOutput = false;
}
if (s.equals("-d")) {
deflate = true;
}
}
Scanner scan = new Scanner(System.in);
StringBuilder buf = new StringBuilder();
while (scan.hasNextLine())
buf.append(scan.nextLine()).append("\n");
Lexer lex = new Lexer(buf.toString());
lex.verbose = verbose;
|
下面是关于解析器的情况: 下面的文本处理过程我会规定 Lite AST JSON 表示方式, 我会给转换器为 GNU/Linux/Android WebView 打包预备接下来使用 Spec 会放在 Wiki 上开发 |
目前发现了规则有一个问题: CallEasy 会把之后所有的 expression 都当成参数: System.out.println getb() a b c
# ^ 会被当成 getb 的参数
System.b 1 2 3 a(1) 2
# ^ 应该是 System.b ... 的参数,却变成了 a 的参数,而 a (1) 2 被解析为 CallEasy
a() 1 2 3 目前认为原来正确的设计是 getb() 使用了 () 来限制参数的范围,所以不会有问题 |
☝️ 所以你们看,还是手写 top-down parser 好 |
不过那样最好就全手写算了,可现在我没这耐心了 |
https://github.com/harc/ohm
https://www.lua.org/manual/5.3/manual.html#3.4.8
和作为临时草稿的 DNF
The text was updated successfully, but these errors were encountered: