首先,假如我们自己建立了一门语言,如何才能让它能够编译运行呢。

第一步,我们要识别语言中的字符串,他们可能是:关键字,字符,数字 等。因此,我们要进行词法分析(LexicalAnalysis)。比如下列表格:我们要将它们归类,并告诉我们的编译器,这些是什么。

我们在这里可以使用自动状态机的模型,当scan 一个字符时,每次进行判断是否构成关键字,或者数字,或者仅仅是一个字符串,或者是运算符。我们在代码里将他们进行分类,为后面的编译服务:

然后,我们就可以动手写一个scanning的program了,假设我们的语言如下:

进而,我们针对每一个字符判断即可。下面,根据代码来讲解:

import java.util.*;public class Scanner {@SuppressWarnings("serial")public static class LexicalException extends Exception {int pos;public LexicalException(String message, int pos) {super(message);this.pos = pos;}public int getPos() {return pos;}}public static enum Kind {IDENTIFIER, INTEGER_LITERAL, BOOLEAN_LITERAL, STRING_LITERAL, KW_x/* x */, KW_X/* X */, KW_y/* y */, KW_Y/* Y */, KW_r/* r */, KW_R/* R */, KW_a/* a */, KW_A/* A */, KW_Z/* Z */, KW_DEF_X/* DEF_X */, KW_DEF_Y/* DEF_Y */, KW_SCREEN/* SCREEN */, KW_cart_x/* cart_x */, KW_cart_y/* cart_y */,KW_polar_a/* polar_a */, KW_polar_r/* polar_r */, KW_abs/* abs */, KW_sin/* sin */,KW_cos/* cos */, KW_atan/* atan */, KW_log/* log */, KW_image/* image */, KW_int/* int */,KW_boolean/* boolean */, KW_url/* url */, KW_file/* file */, OP_ASSIGN/* = */, OP_GT/* > */,OP_LT/* < */, OP_EXCL/* ! */, OP_Q/* ? */, OP_COLON/* : */, OP_EQ/* == */, OP_NEQ/* != */, OP_GE/* >= */, OP_LE/* <= */, OP_AND/* & */, OP_OR/* | */, OP_PLUS/* + */, OP_MINUS/* - */,OP_TIMES/* * */, OP_DIV/* / */, OP_MOD/* % */, OP_POWER/* ** */, OP_AT/* @ */,OP_RARROW/* -> */, OP_LARROW/* <- */, LPAREN/* ( */, RPAREN/* ) */, LSQUARE/* [ */, RSQUARE/* ] */, SEMI/* ; */, COMMA/* , */, EOF;}HashMap<String,Kind> map_keywords=new HashMap<String,Kind>();//建立关键词的表HashMap<Character,Kind> map_op=new HashMap<Character,Kind>();//建立运算符的表public static enum State {START, IN_DIGIT, IN_IDENT, IN_STRING, IN_COMMENT;}//这个是我们的状态机的五个状态:起始,数字,变量,字母,评论public class Token {public final Kind kind;public final int pos;public final int length;public final int line;public final int pos_in_line;//每一个token(指对象),有五个属性public Token(Kind kind, int pos, int length, int line, int pos_in_line) {super();this.kind = kind;this.pos = pos;this.length = length;this.line = line;this.pos_in_line = pos_in_line;}public String getText() {if (kind == Kind.STRING_LITERAL) {return chars2String(chars, pos, length);} elsereturn String.copyValueOf(chars, pos, length);}/*** To get the text of a StringLiteral, we need to remove the enclosing "* characters and convert escaped characters to the represented* character. For example the two characters \ t in the char array* should be converted to a single tab character in the returned String* * @param chars* @param pos* @param length* @return*/private String chars2String(char[] chars, int pos, int length) {StringBuilder sb = new StringBuilder();for (int i = pos + 1; i < pos + length - 1; ++i) {// omit initial// and final "char ch = chars[i];if (ch == '\\') { // handle escapei++;ch = chars[i];switch (ch) {case 'b':sb.append('\b');break;case 't':sb.append('\t');break;case 'f':sb.append('\f');break;case 'r':sb.append('\r'); // for completeness, line termination// chars not allowed in String// literalsbreak;case 'n':sb.append('\n'); // for completeness, line termination// chars not allowed in String// literalsbreak;case '\"':sb.append('\"');break;case '\'':sb.append('\'');break;case '\\':sb.append('\\');break;default:assert false;break;}} else {sb.append(ch);}}return sb.toString();}/*** precondition: 这是一个数字* * 返回数字值*/public int intVal() {assert kind == Kind.INTEGER_LITERAL;return Integer.valueOf(String.copyValueOf(chars, pos, length));}public String toString() {return "[" + kind + "," + String.copyValueOf(chars, pos, length) + "," + pos + "," + length + "," + line+ "," + pos_in_line + "]";}/*** Since we overrode equals, we need to override hashCode.* https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-* * Both the equals and hashCode method were generated by eclipse* */@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + getOuterType().hashCode();result = prime * result + ((kind == null) ? 0 : kind.hashCode());result = prime * result + length;result = prime * result + line;result = prime * result + pos;result = prime * result + pos_in_line;return result;}/*建立自己的equal函数,用于覆盖map的cha'zh* */@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Token other = (Token) obj;if (!getOuterType().equals(other.getOuterType()))return false;if (kind != other.kind)return false;if (length != other.length)return false;if (line != other.line)return false;if (pos != other.pos)return false;if (pos_in_line != other.pos_in_line)return false;return true;}/*** used in equals to get the Scanner object this Token is associated* with.* * @return*/private Scanner getOuterType() {return Scanner.this;}}/*** Extra character added to the end of the input characters to simplify the* Scanner.*/static final char EOFchar = 0;/*** The list of tokens created by the scan method.*/final ArrayList<Token> tokens;/*** An array of characters representing the input. These are the characters* from the input string plus and additional EOFchar at the end.*/final char[] chars;/*** position of the next token to be returned by a call to nextToken*/private int nextTokenPos = 0;Scanner(String inputString) {int numChars = inputString.length();this.chars = Arrays.copyOf(inputString.toCharArray(), numChars + 1); // inputchars[numChars] = EOFchar;tokens = new ArrayList<Token>();}/*** Method to scan the input and create a list of Tokens.* * If an error is encountered during scanning, throw a LexicalException.* * @return* @throws LexicalException*/public Scanner scan() throws LexicalException {/* 定义我们的关键词*/map_keywords.put("x",Kind.KW_x);map_keywords.put("X",Kind.KW_X);map_keywords.put("y",Kind.KW_y);map_keywords.put("Y",Kind.KW_Y);map_keywords.put("r",Kind.KW_r);map_keywords.put("R",Kind.KW_R);map_keywords.put("a",Kind.KW_a);map_keywords.put("A",Kind.KW_A);map_keywords.put("Z",Kind.KW_Z);map_keywords.put("DEF_X",Kind.KW_DEF_X);map_keywords.put("DEF_Y",Kind.KW_DEF_Y);map_keywords.put("SCREEN",Kind.KW_SCREEN);map_keywords.put("cart_x",Kind.KW_cart_x);map_keywords.put("cart_y",Kind.KW_cart_y);map_keywords.put("polar_a",Kind.KW_polar_a);map_keywords.put("polar_r",Kind.KW_polar_r);map_keywords.put("abs",Kind.KW_abs);map_keywords.put("sin",Kind.KW_sin);map_keywords.put("cos",Kind.KW_cos);map_keywords.put("atan",Kind.KW_atan);map_keywords.put("log",Kind.KW_log);map_keywords.put("image",Kind.KW_image);map_keywords.put("int",Kind.KW_int);map_keywords.put("boolean",Kind.KW_boolean);map_keywords.put("url",Kind.KW_url);map_keywords.put("file",Kind.KW_file);map_op.put('?', Kind.OP_Q);map_op.put(':', Kind.OP_COLON);map_op.put('&', Kind.OP_AND);map_op.put('|', Kind.OP_OR);map_op.put('+', Kind.OP_PLUS);map_op.put('@', Kind.OP_AT);map_op.put('%', Kind.OP_MOD);map_op.put(';', Kind.SEMI);map_op.put(',', Kind.COMMA);map_op.put('(', Kind.LPAREN);map_op.put(')', Kind.RPAREN);map_op.put('[', Kind.LSQUARE);map_op.put(']', Kind.RSQUARE);int pos = 0;int line = 1;int sum=0;String temp="";State state = State.START;int startPos = 1; int pos_temp=0;//自动状态机开始,在其中定义好每一个字符扫入后的状态转移路线。笨一点就用switch_case实现就可以了      while (pos <= chars.length) {char ch=EOFchar;switch (state) {case START: { //开始态ch = pos < chars.length ? chars[pos] : EOFchar;switch (ch) {case '=': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_EQ,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_ASSIGN,pos, 1,line,startPos));pos++;startPos++;}}break;case '-': {if(chars[pos+1]=='>'){tokens.add(new Token(Kind.OP_RARROW,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_MINUS,pos, 1,line,startPos));pos++;startPos++;}}break;case '>': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_GE,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_GT,pos, 1,line,startPos));pos++;startPos++;}}break;case '!': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_NEQ,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_EXCL,pos, 1,line,startPos));pos++;startPos++;}}break;case '<': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_LE,pos, 2,line,startPos));pos+=2;startPos+=2;}else if(chars[pos+1]=='-'){tokens.add(new Token(Kind.OP_LARROW,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_LT,pos, 1,line,startPos));pos++;startPos++;}}break;case '*': {if(chars[pos+1]=='*'){tokens.add(new Token(Kind.OP_POWER,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_TIMES,pos, 1,line,startPos));pos++;startPos++;}}break;case '/': {if(chars[pos+1]=='/'){state=State.IN_COMMENT;pos_temp=pos;pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_DIV,pos, 1,line,startPos));pos++;startPos++;}}break;case '\r':{if(chars[pos+1]=='\n'){line++;startPos=1;pos+=2;}else{line++;pos++;startPos=1;}}break;case '0': {tokens.add(new Token(Kind.INTEGER_LITERAL,pos, 1,line,startPos));pos++;startPos++;}break;case '\n':{line++;pos++;startPos=1;}break;case '\"':{state=State.IN_STRING;pos_temp=pos;pos++;}break;case EOFchar:{pos++;}break;default: {if(map_op.containsKey(ch)){tokens.add(new Token(map_op.get(ch), pos, 1,line,startPos));pos++;startPos++;} else if (Character.isDigit(ch)) {sum=0;state = State.IN_DIGIT;pos_temp=pos;} else if (Character.isJavaIdentifierStart(ch)) {state = State.IN_IDENT;pos_temp=pos;temp="";} else if (Character.isWhitespace(ch)){pos++;startPos++;}else {throw new LexicalException("Illegal Character",pos); }}}// switch (ch)}  break;case IN_DIGIT: {//数字态ch = pos < chars.length ? chars[pos] : EOFchar;if(Character.isDigit(ch)){temp+=ch;pos++;}else{for (int i = 0; i < temp.length(); i++) {   sum  = sum * 10 + (temp.charAt(i) - '0');if (sum < 0)  throw new LexicalException("Integeal too big!",pos_temp);}tokens.add(new Token(Kind.INTEGER_LITERAL, pos_temp, pos - pos_temp,line,startPos));startPos+=pos-pos_temp;pos_temp=0;temp="";state=State.START;}}break;case IN_IDENT: {//变量ch = pos < chars.length ? chars[pos] : EOFchar; if (Character.isLetterOrDigit(ch) || ch=='$' || ch=='_') {temp+=ch;pos++;}else {if(map_keywords.containsKey(temp)){tokens.add(new Token(map_keywords.get(temp), pos_temp, pos - pos_temp,line,startPos));}else if(temp.equals("true")||temp.equals("false")){tokens.add(new Token(Kind.BOOLEAN_LITERAL, pos_temp, pos - pos_temp,line,startPos));}else{tokens.add(new Token(Kind.IDENTIFIER, pos_temp, pos - pos_temp,line,startPos));}state = State.START;startPos+=pos-pos_temp;temp="";pos_temp=0;}  }  break;case IN_STRING: {//字符串ch = pos < chars.length ? chars[pos] : EOFchar;//System.out.println(ch);if (ch=='\n'||ch=='\t'||ch=='\f'||ch=='\r'){throw new LexicalException("Illegal Character for String Literal",pos); }else if(ch=='\\'){if(chars[pos+1]=='n'||chars[pos+1]=='t'||chars[pos+1]=='b'||chars[pos+1]=='f'||chars[pos+1]=='r'||chars[pos+1]=='\"'||chars[pos+1]=='\''||chars[pos+1]=='\\'){temp=temp+ch+chars[pos+1];pos+=2;}else{throw new LexicalException("Illegal Character for String Literal",pos+1);    }}else if (ch!=EOFchar&&ch!='\"') {temp+=ch;pos++;}else {if(ch!='\"') {throw new LexicalException("Missing \" in the end of String",pos);}else{tokens.add(new Token(Kind.STRING_LITERAL, pos_temp, pos - pos_temp+1,line,startPos));pos++;state = State.START;startPos+=pos-pos_temp;temp="";}}  }  break;case IN_COMMENT: {//评论ch = pos < chars.length ? chars[pos] : EOFchar;if (ch!='\n'&&ch!='\r'&&ch!=EOFchar) {pos++;}else {state=State.START;startPos+=pos-pos_temp;}}  break;default:  throw new LexicalException("ILLEGAL CHARACTER",pos); }// switch(state)} // whiletokens.add(new Token(Kind.EOF, pos-2, 0,line,startPos));return this;}/*** Returns true if the internal interator has more Tokens* * @return*/public boolean hasTokens() {return nextTokenPos < tokens.size();}/*** Returns the next Token and updates the internal iterator so that the next* call to nextToken will return the next token in the list.* * It is the callers responsibility to ensure that there is another Token.* * Precondition: hasTokens()* * @return*/public Token nextToken() {return tokens.get(nextTokenPos++);}/*** Returns the next Token, but does not update the internal iterator. This* means that the next call to nextToken or peek will return the same Token* as returned by this methods.* * It is the callers responsibility to ensure that there is another Token.* * Precondition: hasTokens()* * @return next Token.*/public Token peek() {return tokens.get(nextTokenPos);}/*** Resets the internal iterator so that the next call to peek or nextToken* will return the first Token.*/public void reset() {nextTokenPos = 0;}/*** Returns a String representation of the list of Tokens*/public String toString() {StringBuffer sb = new StringBuffer();sb.append("Tokens:\n");System.out.println(tokens.size());for (int i = 0; i < tokens.size(); i++) {sb.append(tokens.get(i)).append('\n');}return sb.toString();}}
     while (pos <= chars.length) {char ch=EOFchar;switch (state) {case START: { //开始态ch = pos < chars.length ? chars[pos] : EOFchar;switch (ch) {case '=': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_EQ,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_ASSIGN,pos, 1,line,startPos));pos++;startPos++;}}break;case '-': {if(chars[pos+1]=='>'){tokens.add(new Token(Kind.OP_RARROW,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_MINUS,pos, 1,line,startPos));pos++;startPos++;}}break;case '>': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_GE,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_GT,pos, 1,line,startPos));pos++;startPos++;}}break;case '!': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_NEQ,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_EXCL,pos, 1,line,startPos));pos++;startPos++;}}break;case '<': {if(chars[pos+1]=='='){tokens.add(new Token(Kind.OP_LE,pos, 2,line,startPos));pos+=2;startPos+=2;}else if(chars[pos+1]=='-'){tokens.add(new Token(Kind.OP_LARROW,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_LT,pos, 1,line,startPos));pos++;startPos++;}}break;case '*': {if(chars[pos+1]=='*'){tokens.add(new Token(Kind.OP_POWER,pos, 2,line,startPos));pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_TIMES,pos, 1,line,startPos));pos++;startPos++;}}break;case '/': {if(chars[pos+1]=='/'){state=State.IN_COMMENT;pos_temp=pos;pos+=2;startPos+=2;}else{tokens.add(new Token(Kind.OP_DIV,pos, 1,line,startPos));pos++;startPos++;}}break;case '\r':{if(chars[pos+1]=='\n'){line++;startPos=1;pos+=2;}else{line++;pos++;startPos=1;}}break;case '0': {tokens.add(new Token(Kind.INTEGER_LITERAL,pos, 1,line,startPos));pos++;startPos++;}break;case '\n':{line++;pos++;startPos=1;}break;case '\"':{state=State.IN_STRING;pos_temp=pos;pos++;}break;case EOFchar:{pos++;}break;default: {if(map_op.containsKey(ch)){tokens.add(new Token(map_op.get(ch), pos, 1,line,startPos));pos++;startPos++;} else if (Character.isDigit(ch)) {sum=0;state = State.IN_DIGIT;pos_temp=pos;} else if (Character.isJavaIdentifierStart(ch)) {state = State.IN_IDENT;pos_temp=pos;temp="";} else if (Character.isWhitespace(ch)){pos++;startPos++;}else {throw new LexicalException("Illegal Character",pos); }}}// switch (ch)}  break;case IN_DIGIT: {//数字态ch = pos < chars.length ? chars[pos] : EOFchar;if(Character.isDigit(ch)){temp+=ch;pos++;}else{for (int i = 0; i < temp.length(); i++) {   sum  = sum * 10 + (temp.charAt(i) - '0');if (sum < 0)  throw new LexicalException("Integeal too big!",pos_temp);}tokens.add(new Token(Kind.INTEGER_LITERAL, pos_temp, pos - pos_temp,line,startPos));startPos+=pos-pos_temp;pos_temp=0;temp="";state=State.START;}}break;case IN_IDENT: {//变量ch = pos < chars.length ? chars[pos] : EOFchar; if (Character.isLetterOrDigit(ch) || ch=='$' || ch=='_') {temp+=ch;pos++;}else {if(map_keywords.containsKey(temp)){tokens.add(new Token(map_keywords.get(temp), pos_temp, pos - pos_temp,line,startPos));}else if(temp.equals("true")||temp.equals("false")){tokens.add(new Token(Kind.BOOLEAN_LITERAL, pos_temp, pos - pos_temp,line,startPos));}else{tokens.add(new Token(Kind.IDENTIFIER, pos_temp, pos - pos_temp,line,startPos));}state = State.START;startPos+=pos-pos_temp;temp="";pos_temp=0;}  }  break;case IN_STRING: {//字符串ch = pos < chars.length ? chars[pos] : EOFchar;//System.out.println(ch);if (ch=='\n'||ch=='\t'||ch=='\f'||ch=='\r'){throw new LexicalException("Illegal Character for String Literal",pos); }else if(ch=='\\'){if(chars[pos+1]=='n'||chars[pos+1]=='t'||chars[pos+1]=='b'||chars[pos+1]=='f'||chars[pos+1]=='r'||chars[pos+1]=='\"'||chars[pos+1]=='\''||chars[pos+1]=='\\'){temp=temp+ch+chars[pos+1];pos+=2;}else{throw new LexicalException("Illegal Character for String Literal",pos+1);    }}else if (ch!=EOFchar&&ch!='\"') {temp+=ch;pos++;}else {if(ch!='\"') {throw new LexicalException("Missing \" in the end of String",pos);}else{tokens.add(new Token(Kind.STRING_LITERAL, pos_temp, pos - pos_temp+1,line,startPos));pos++;state = State.START;startPos+=pos-pos_temp;temp="";}}  }  break;case IN_COMMENT: {//评论ch = pos < chars.length ? chars[pos] : EOFchar;if (ch!='\n'&&ch!='\r'&&ch!=EOFchar) {pos++;}else {state=State.START;startPos+=pos-pos_temp;}}  break;default:  throw new LexicalException("ILLEGAL CHARACTER",pos); }// switch(state)} // whiletokens.add(new Token(Kind.EOF, pos-2, 0,line,startPos));return this;}/*** Returns true if the internal interator has more Tokens* * @return*/public boolean hasTokens() {return nextTokenPos < tokens.size();}/*** Returns the next Token and updates the internal iterator so that the next* call to nextToken will return the next token in the list.* * It is the callers responsibility to ensure that there is another Token.* * Precondition: hasTokens()* * @return*/public Token nextToken() {return tokens.get(nextTokenPos++);}/*** Returns the next Token, but does not update the internal iterator. This* means that the next call to nextToken or peek will return the same Token* as returned by this methods.* * It is the callers responsibility to ensure that there is another Token.* * Precondition: hasTokens()* * @return next Token.*/public Token peek() {return tokens.get(nextTokenPos);}/*** Resets the internal iterator so that the next call to peek or nextToken* will return the first Token.*/public void reset() {nextTokenPos = 0;}/*** Returns a String representation of the list of Tokens*/public String toString() {StringBuffer sb = new StringBuffer();sb.append("Tokens:\n");System.out.println(tokens.size());for (int i = 0; i < tokens.size(); i++) {sb.append(tokens.get(i)).append('\n');}return sb.toString();}}

转载于:https://www.cnblogs.com/chris1030/p/9795390.html

不知不觉,写了一个编译器(一)相关推荐

  1. 学了编译原理能否用 Java 写一个编译器或解释器?

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  2. 从零写一个编译器(完结):总结和系列索引

    前言 这个系列算作我自己的学习笔记,到现在已经有十三篇了,加上这篇一共十四篇.一步一步的从词法分析到语法分析.语义分析,再到代码生成,准备在这一篇做一个总结收尾和一个这个系列以前文章的索引. (另外, ...

  3. 从零写一个编译器(十):编译前传之直接解释执行

    项目的完整代码在 C2j-Compiler 前言 这一篇不看也不会影响后面代码生成部分 现在经过词法分析语法分析语义分析,终于可以进入最核心的部分了.前面那部分可以称作编译器的前端,代码生成代码优化都 ...

  4. 从零写一个编译器(九):语义分析之构造抽象语法树(AST)

    项目的完整代码在 C2j-Compiler 前言 在上一篇完成了符号表的构建,下一步就是输出抽象语法树(Abstract Syntax Tree,AST) 抽象语法树(abstract syntax ...

  5. 从零写一个编译器(三):语法分析之几个基础数据结构

    项目的完整代码在 C2j-Compiler 写在前面 这个系列算作为我自己在学习写一个编译器的过程的一些记录,算法之类的都没有记录原理性的东西,想知道原理的在龙书里都写得非常清楚,但是我自己一开始是不 ...

  6. 从零写一个编译器(一):输入系统和词法分析

    项目的完整代码在 C2j-Compiler 前言 从半抄半改的完成一个把C语言编译到Java字节码到现在也有些时间,一直想写一个系列来回顾整理一下写一个编译器的过程,也算是学习笔记吧.就从今天开始动笔 ...

  7. java c语言 for_Java能写C语言编译器吗

    用java是可以写语言编译器的,用任何语言工具写都可以.各语言开发工具间只有开发效率的差异,没有可行不可行的区别. 编译器其实就是一个翻译工具,它可以把代码直接翻译成二进制文件交给CPU执行(二进制指 ...

  8. c语言实现一个编译器生成语法树,运用JavaScript构造C语言子集的编译器

    使用JavaScript构造C语言子集的编译器 jCompiler是我一年前完成的一个课程作业.目的是尝试为编程语言提供基于浏览器的编译器实现+骗取高分(这才是重点). 实现的功能有:词法分析.语法分 ...

  9. 从零开始写第一个Android应用程序

    学习Android准备知识 安卓四层系统构成: 第一层:最底层 Linux层 第二层:函数库层 由C或者C++写 第三层:Application FrameWork 应用框架层 第四层:最上层 应用层 ...

  10. 用 python 写了一个日记本

    写一个随机任务抽取器 一.前言 二.逻辑构思 2.1 目标实现 2.2 搭建开发环境 2.3 Pyinstaller 打包 三.效果展示 3.1 初始化和添加日记 3.2 查看日记 3.3 删除日记 ...

最新文章

  1. share extension 不显示_高亮显示系统日志应该用什么命令
  2. foo、bar到底是什么意思
  3. python3.8安装插件locust报错error: Microsoft Visual C++ 14.0 is required. Get it with Microsoft Visual C++
  4. Knative 实战:如何在 Knative 中配置自定义域名及路由规则
  5. 利用公众号 + WeRoBot开发一款AI应用
  6. 嵌入式根文件系统制作
  7. bzoj1339[Baltic2008]Mafia*
  8. Python网络爬虫开发实战,关于过程中的异常处理
  9. 数据科学和人工智能技术笔记 七、特征工程
  10. 使用STL map 用 string 做索引 插入删除数据
  11. 1008 数组元素循环右移问题 (20 分)—PAT (Basic Level) Practice (中文)
  12. linux上jdk安装
  13. 计算机速录水平考试,汉字速录水平测试(速录证考试报名网站)
  14. node_注册页面+连接数据库+加密
  15. 敏捷开发项目管理软件
  16. matlab control包,免费试用Instrument Control Toolbox
  17. 整一篇整一篇,python3实现自动重启路由器的上的花生壳(selenium)
  18. Android N开发 你需要知道的一切
  19. 电脑重装系统后Win11底部任务栏大小调整方法
  20. 嵌入式系统——复杂指令集系统与精简指令集系统(CISCRISC)

热门文章

  1. android httpget 参数,如何在Android中向HTTP GET请求添加参数?
  2. c语言 时间函数,C/C+时间相关的函数
  3. pcl dll load failed: 找不到指定的模块。_解决cuda10.1+tensorflow-gpu出现“cudart64_100.dll”问题...
  4. HTML画廊效果,HTML5实践-使用css装饰图片画廊的代码分享(一)
  5. 2022年 微信大数据挑战赛
  6. C++ vector和set的区别
  7. mtk6595能否运行linux,“被妖魔化”的联发科MTK6595到底如何?
  8. linux创建表空间 没有权限,ORA-12913: 无法创建字典管理的表空间
  9. php 小米路由器_云水日记-捣鼓小米路由器开发版本
  10. 动态规划之状态压缩DP