编译原理
stateDiagram-v2
  源代码 --> 词法分析
  state 前端 {
    词法分析 --> 语法分析
    语法分析 --> 语义分析
  }
  语义分析 --> 生成中间代码
  state 后端 {
    生成中间代码 --> 优化
    优化 --> 生成目标代码
  }
词法分析
有限自动机
要实现一个词法分析器,首先需要写出每个词法的正则表达式,并画出有限自动机,之后,只要用代码表示这种状态迁移过程就可以了
age >= 45 的此法解析自动机:
stateDiagram-v2
  初始 --> 比较操作符>: >
  比较操作符> --> 比较操作符>=: =
  初始 --> ID: 字母
  ID --> ID: 字母或数字
  初始 --> 数字字面量: 数字
  数字字面量 --> 数字字面量: 数字
DfaState newState = DfaState.Initial;
if (isAlpha(ch)) {              //第一个字符是字母
    newState = DfaState.Id; //进入Id状态
    token.type = TokenType.Identifier;
    tokenText.append(ch);
} else if (isDigit(ch)) {       //第一个字符是数字
    newState = DfaState.IntLiteral;
    token.type = TokenType.IntLiteral;
    tokenText.append(ch);
} else if (ch == '>') {         //第一个字符是>
    newState = DfaState.GT;
    token.type = TokenType.GT;
    tokenText.append(ch);
}
使用正则表达式描述词法:
Id :        [a-zA-Z_] ([a-zA-Z_] | [0-9])*
IntLiteral: [0-9]+
GT :        '>'
GE :        '>='
语法分析
语法规则描述
BNF:
add ::= mul | add + mul
mul ::= pri | mul * pri
pri ::= Id | Num | (add) 
扩展BNF(EBNF):
// 会用到类似正则表达式的一些写法
add -> mul (+ mul)*
上下文无关文法
上下文无关指的是无论在任何情况下,文法的推导规则都是一样的
描述整数加法与乘法的文法,在解析后,可以形成一颗AST:
additiveExpression
    :   multiplicativeExpression
    |   additiveExpression Plus multiplicativeExpression
    ;
multiplicativeExpression
    :   IntLiteral
    |   multiplicativeExpression Star IntLiteral
    ;
“2+3*5” 的推导过程:
-->additiveExpression + multiplicativeExpression
-->multiplicativeExpression + multiplicativeExpression
-->IntLiteral + multiplicativeExpression
-->IntLiteral + multiplicativeExpression * IntLiteral 
-->IntLiteral + IntLiteral * IntLiteral
递归下降
上级文法嵌套下级文法,上级的算法调用下级的算法
消除左递归:
对于加法与乘法的文法:
add -> mul | add + mul   
会陷入无限递归,那就引入一个终止条件,也就是空集来终止递归:
add -> mul add'
add' -> + mul add' | ε
// EBNP表达
add -> mul (+ mul)* 
Antlr
词法规则文件:
lexer grammar Hello;  //lexer关键字意味着这是一个词法规则文件,要与文件名相同。
@header {
package antlrtest;
}
//关键字
If :               'if' | '如果';   //可以在程序里用‘如果’来代替'if'
Int :              'int';
//常量
IntLiteral:        [0-9]+;
StringLiteral:      '"' .*? '"' ;  //字符串常量
//操作符
AssignmentOP:       '=' ;    
RelationalOP:       '=='|'>'|'>='|'<' |'<=' ;    
Star:               '*';
Plus:               '+';
Sharp:              '#';
SemiColon:          ';';
Dot:                '.';
Comm:               ',';
LeftBracket :       '[';
RightBracket:       ']';
LeftBrace:          '{';
RightBrace:         '}';
LeftParen:          '(';
RightParen:         ')';
//标识符
Id :                [a-zA-Z_] ([a-zA-Z_] | [0-9])*;
//空白字符,抛弃
Whitespace:         [ \t]+ -> skip;
Newline:            ( '\r' '\n'?|'\n')-> skip;
// 语法分析器
expression
    :   assignmentExpression
    |   expression ',' assignmentExpression
    ;
assignmentExpression
    :   additiveExpression
    |   Identifier assignmentOperator additiveExpression
    ;
assignmentOperator
    :   '='
    |   '*='
    |  '/='
    |   '%='
    |   '+='
    |   '-='
    ;
additiveExpression
    :   multiplicativeExpression
    |   additiveExpression '+' multiplicativeExpression
    |   additiveExpression '-' multiplicativeExpression
    ;
multiplicativeExpression
    :   primaryExpression
    |   multiplicativeExpression '*' primaryExpression
    |   multiplicativeExpression '/' primaryExpression
    |   multiplicativeExpression '%' primaryExpression
    ;
# 生成词法分析器的java源码
antlr Hello.g4
# 生成语法分析器
antlr PlayScript.g4
# 输入表达式查看AST
grun antlrtest.PlayScript expression -gui